8:下列多重继承时的二义性问题如何解决?
class A{ //类A的定义
public:
void print () {cout<<"Hello, this is A"<<endl;}
};
class B{ //类B的定义
public:
void print () {cout<<"Hello, this is B"<<endl;}
};
class C : public A, public B{ //类C由类A和类B共同派生而来
public:
void disp () {print ();}//编译器无法决定采用A类中定义的版本还是B类中的版本
};
解答:,如:
void disp () {
A: : print () ; //加成员名限定A::
}
但更好的办法是在类C中也定义一个同名print函数,根据需要调用A::print()还是B::print(),从 而实现对基类同名函数的隐藏
9:下列公共基类导致的二义性如何解决?
class A{ //公共基类
public: //public 成员列表
void print(){
cout << "this is x in A: " <<endl;}
class B: public A{};
class C: public A{};
class D : public B, public C{};
void main(){
D d; //声明一个D类对象d
A* pa=(A*) &d; //上行转换产生二义性
d.print () ; //print ()具有二义性,系统不知道是调用B类的还是C类的print ()函数
}
注意:,
解答:1) main函数中语句“d.print();”编译错误,可改为以下的一种:
d.B::print(); d.C::print();
若改为“d.A::print();”又会如何呢?
由于d对象中有两个A类对象,故编译会报“基类A不明确”。
2)语句“A*pa=(A*)&d;sizeof 指针”产生的二义性是由于d中含有两个基类对象A,隐式 转换时不知道让 pa指向哪个子对象,从而出错。可改为以下的一种:
A*pa=(A*)(B*)&d; //上行转换
A*pa=(A*)(C*)&d; //上行转换
事实上,使用关键字virtual将共同基类A声明为虚基类,可有效解决上述 问题。
10:下面哪种情况下,B不能隐式转换为A ( ) ? (2011 •腾讯)
A. class B:publicA{} B. classA : public B{}
C. class B {operator A();} D. class A{A(const B&);}
解答:B。因为子类包含了父类部分,所以子类可以转换为父类,但是相反, 父类没有子类额外定义的部分,所以不能转换为子类,故A正确,而B错误。
非C++内建型别A和B,在以下几种情况下B能隐式转化为A。
1)B公有继承自A,可以是间接继承的。
class B : public A{
};
此时若有“A a; B b;”,则 “a=b;”合法。
2)B中有类型转换函数。
class B{
operator A();
};
此时若有“A a; B b;”,则“a=b;”合法。
3)A实现了非explicit的参数为B (可以有其他带默认值的参数)的构造函 数
class A {
A(const B&);
};
此时若有“A a; B b;”,则“a=b;”合法。
11:调用一成员函数时,使用动态联编的情况是()。(2011 •淘宝)
A.通过对象调用一虚函数 B.通过指针或引用调用一虚函数
C.通过对象调用静态函数 D.通过指针或引用调用一静态函数
解答:B。
结合一段示例代码来看虚函数的作用,以帮助大家理解多态的意义所在。
例2:下述代码的输出结果是什么?
class base{
public:
virtual void disp(){cout << "hello, base1" <<endl;} void disp2(){cout <<"hello, base2" << endl;}
};
class child1:public base{
public:
void disp() {cout << "hello, child1" << endl;}
void disp2(){cout <<"hello, child2" << endl;}
void main(){
base * base=NULL;
child1 obj child1;
base=&obj childl;
base->disp();
base->disp2();
解答:输出:hello, childl
hello, base2
从上述代码可见,通过指针访问函数时:
1)
2)
13:构造函数为什么不能为虚函数?
解答:假设有如下代码:
class A{
A() { }
};
class B : public A{
B():A() { }
};
int main(){
B b;
B*pb=&b;
}
则构造B类的对象时:
1.根据继承的性质,构造函数执行顺序是:
A()B()
2.根据虚函数的性质,如果A的构造函数为虚函数,且B类也给出了构造函数,则应该只执行B类的构造函数,不再执行A类的构造函数。这样A就不能构造了。
3.这样1和2就发生了矛盾。
另外,virtual函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用virtual函数来完成你想完成的动作。
14:哪些函数不能为虚函数?
解答:常见的不能声明为虚函数的有:、、、,而内联成员函数、赋值操作符重载函数即使声明为虚函数也无意义。
1)为什么C++不支持普通函数为虚函数?
,声明为虚函数也没有什么意义,因此编译器会在编译时绑定函数。
为什么C++不支持构造函数为虚函数?
上例己经给出了答案。
2)为什么C++不支持静态成员函数为虚函数?
3)为什么C++不支持友元函数为虚函数?
因为
以下两种函数被声明为虚函数时,虽然编译器不会报错,但是毫无意义。
内联函数:内联函数是为了在代码中直接展开,减少函数调用花费的代价,虚函数是为了在继承后,对象能够准确地执行自己的动作,这是不可能统一的。即使虚函数被声明为内联函数,编译器遇到这种情况根本不会把这样的函数内联展开,而是当作普通函数来处理。
赋值运算符:虽然可以在基类中将成员函数operator定义为虚函数,但这样做没有意义。赋值操作符重载函数要求形参与类本身类型相同,故基类中的赋值操作符形参类型为基类类型,即使声明为虚函数,也不能作为子类的赋值操作符。
15:以下描述正确的是()。(2011 •盛大游戏)
A.虚函数是可以内联的,可以减少函数调用的开销提高效率
B.类里面可以同时存在函数名和参数都一样的虚函数和静态函数
C.父类的析构函数是非虚的,但是子类的析构函数是虚的,delete子类对象指针会调用父类的析构函数
D •以上都不对
解答:C。C中delete子类对象指针会调用父类的析构函数(即使子类的析构 函数不是虚的,对子类对象指针调用析构函数,也会调用父类的析构函数), 但若delete父类对象指针却不会调用子类的析构函数(因为父类的析构函数 不是虚函数,不执行动态绑定)。
16:以下代码的输出结果是()。(2012 •小米)
class B{
public:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论