今天看到《C++ primer》上说:可以用派生类对象初始化基类对象,根据是派生类对象可以赋值给基类的对象的引用。这里我觉得有个语义上的问题:派生类在继承基类的时候,基类的private成员是不可见的,那么基类初始化private对象的时候,就用了派生类的不可见成员去初始化它了。
先贴段测试代码:
1 #include<iostream>
2 using namespace std;
3 class A
4 {
5 int mem1,mem2;
6 public:
7 A(const A& a);
8 A(int a, int b):mem1(a),mem2(b){}
9 int fun1(){return mem1;}
10 int fun2(){return mem2;}
11 };
12 A::A(const A& a)
13 {
14 mem1 = a.mem1;
15 mem2 = a.mem2;
16 cout << "A's copy constructor called"<<endl;
17 }
18 class B : public A
19 {
20 int mem3;
21 public:
22 B(int a, int b, int c): A(a,b),mem3(c){}
23 int fun3(){return fun1()};
24 };
25 int main()
26 {
27 B b(1,2,3);
28 A aob(b);
29 }
30
这段代码输出:
A's copy constructor called(这是用G++编译器的,DEV C++ 编译通过,可是运行没有输出)确实如书上说的派生类对象可以赋值给基类的对象的引用,所以调用了拷贝构造函数。其实根据《inside the C++ object model》的说法,派生类的对象中将会保存基类的non-static数据成员的,那么即使不可见,可以用来初始化也在情理之中。
可是再看被初始化对象调用其成员函数的代码:
1 #include<iostream>
2 using namespace std;
3 class A
4 {
5 int mem1,mem2;
6 public:
7 A(const A& a);
8 A(int a, int b):mem1(a),mem2(b){}
9 int fun1(){return mem1;}
10 int fun2(){return mem2;}
11 };
12 A::A(const A& a)
13 {
14 mem1 = a.mem1;
15 mem2 = a.mem2;
16 cout << "A's copy constructor called"<<endl;
17 }
18 class B : public A
19 {
20 int mem3;
21 public:
22 B(int a, int b, int c): A(a,b),mem3(c){}
23 int fun3(){return fun1()};
24 };
25 int main()
26 {
27 B b(1,2,3);
28 A aob(b);
29 cout <<aob.fun1() << aob.fun2();//the //difference
30 }
31
这就编译错误了:tess.cpp:28:36: error: request for member ‘fun2’ in ‘aob’, which is of non-class type ‘A(B)’这在两个上述编译器都是这样的结果。那么这个对象就无法调用基类的函数了。
我个人肤浅的推断:A(B)将被编译器认为是一种新的类型对待,那么怎么确定这种类型的接口函数呢?这不就有问题了吗?
我再多此一举的实验下如下代码:
1 #include<iostream>
2 using namespace std;
3 class A
4 {
5 int mem1,mem2;
6 public:
7 A(const A& a);
8 A(int a, int b):mem1(a),mem2(b){}
9 int fun1(){return mem1;}
10 int fun2(){return mem2;}
11 };
12 A::A(const A& a)
13 {
14 mem1 = a.mem1;
15 mem2 = a.mem2;
16 cout << "A's copy constructor called"<<endl;
17 }
18 class B : public A
19 {
20 int mem3;
21 public:
22 B(int a, int b, int c): A(a,b),mem3(c){}
23 int fun3(){return fun1();}
24 };
25 int main()
26 {
27 B b(1,2,3);
28 A aob(b);
29 cout <<aob.fun3();// the difference
30 }
31
结果是编译错误:‘class A’ has no member named ‘fun3’这一点也不意外,那么这样的对象不就真的没有了接口了?小弟我虚心等待大牛们的解答,希望能在原理上给俺个解释,不胜感激!