http://blog.csdn.net/wuzhekai1985/article/details/6628212
问题 6:非C++内建型别A 和B,在哪几种情况下B 能隐式转化为A?
(1)class A { ...... }; class B : public A { ……} ; // B 公有继承自A,可以是间接继承的
(2)class A { ...... }; class B { operator A() { return A::A(); } ......}; // B 实现了到A 的类型转化
(3)class A { A( const B& ); } ; // A 实现了non-explicit 的参数为B(可以有其他带默认值的参数)构造函数
提供隐式转换时,应避免出现二义性。比如上面的几种方式,如果即定义了(2)又定义了(3),就存在二义性。因为编译器可以用两种方式将B转换为A,一是用A的构造函数,另一种是用B的类型转换符。最佳实践:避免二义性最好的办法是避免编写互相提供隐式转换的成对的类。《C++ Primer》。
问题 7:下面这个程序有什么问题?
- #include <iostream>
- using namespace std;
- class A
- {
- private:
- int value;
- public:
- A(int n) { value = n; }
- A(A other){ value = other.value; }
- void Print(){ cout << value << endl; }
- };
- int main()
- {
- A a = 10;
- A b = a;
- b.Print();
- return 0;
- }
编译错误, A(A other){} 这个复制构造函数定义有误,该函数的形参只能是本类类型对象的引用,常用const修饰《C++ Primer》。应该改成这样 A(const A&other) { value = other.value; }。复制构造函数可以用于:
(1)根据另一个同类型的对象显示或隐式初始化一个对象
string s = "hello";
首先会调用接受一个C风格字符串形参的string构造函数,创建临时对象,然后调用复制构造函数,将s初始化为那个临时对象的副本。
(2)复制一个对象,将它作为实参传递给一个函数
void foo(string s);
(3)从函数返回复制一个对象
string foo();
(4)初始化容器中的元素。
vector<string> svec(5);
首先调用string默认构造函数创建一个临时值,然后将这个临时值复制给svec的每一个元素,即调用string复制构造函数。
(5)根据元素初始化列表初始化数组元素
比如下面这个函数,初始化数组a 时调用的是复制构造函数。而初始化数组b时调用的是默认构造函数。而初始化数组c时,由于它有4个元素,而初始化列表只有2个,因此前两个元素的初始化调用复制构造函数,后两个元素的初始化调用默认构造函数。
- #include <iostream>
- using namespace std;
- class A
- {
- public:
- A() { value=1;cout<<"A Default Constructor"<<endl;}
- A(int v) {value=v;cout<<"A Copy Constructor"<<endl;}
- int value;
- };
- int main()
- {
- A a[2]={1,2};
- A b[2];
- A c[4]={1,2};
- return 0;
- }
问题8:构造函数、静态函数、内联函数可不可以是虚函数?
构造函数和静态函数不可以、内联函数可以
构造函数不可以为虚函数:虚函数的调用是通过一个虚指针来实现的,而这个虚指针是在构造过程中设定的。
静态函数不可为虚函数:静态函数的调用是不需要实例的,而虚函数需要通过从一个实例中获取虚指针,进而获取函数的地址,从而实现动态绑定。
内联函数可以:内联是在编译阶段用代码换调用,而虚函数是在运行期动态绑定。虽然可以,但是一般不会这样做,代价太大了。
问题9:析构函数必须是虚函数吗?
答案是并不是必须的。如果类被设计成能被继承,析构函数必须是虚函数。否则可以不为虚函数。析构函数写成虚函数主要是为了在实现多态时不造成内存泄露。比如下面这段程序,B的析构函数不会被调用,如果将A的析构函数写成虚函数,则B的析构函数可以被调用。
- #include <iostream>
- using namespace std;
- class A
- {
- public:
- A() {cout<<"A Constructor\n";}
- ~A() {cout<<"A Destructor\n";}
- };
- class B:public A
- {
- public:
- B() { cout<<"B Constructor\n";}
- ~B() { cout<<"B Destructor\n";}
- };
- int main()
- {
- A *pa=new B();
- delete pa;
- return 0;
- }
- #include <iostream>
- using namespace std;
- struct Point3D
- {
- int x;
- int y;
- int z;
- };
- int main()
- {
- Point3D* pPoint = NULL;
- int offset = (int)(&(pPoint->z));
- cout<<offset<<endl;
- return 0;
- }
如果是&(pPoint->x)和&(pPoint->y),则结果为0和4。
如果pPoint不为空,例如 Point3D* pPoint = new Point3D; 三个成员变量的地址依次相差4。