现在的位置: 首页 > 综合 > 正文

我的fucking in c++读后感–理解继承和组合!

2012年05月07日 ⁄ 综合 ⁄ 共 2285字 ⁄ 字号 评论关闭

1、继承类默认继承了基类的成员函数,即,在不重定义的前提下,y.f( )y.X::f( )调用的同一个函数

而组合类则必须通过成员类对象进行函数调用,一个类的构造函数调用顺序是先基类,再组合类,最后会进行本类的构造函数。

如果重定义了基类的函数,则基类的同名函数全部自动隐藏。所谓“全部”是因为,可能在基类中有多个同名的重载函数,它们全部隐藏

覆盖是指派生类函数覆盖基类函数
函数名相同;
参数相同;
基类函数必须有Virtual关键字;
不同的范围(派生类和基类)。
隐藏是指派生类屏蔽了基类的同名函数相同

     1、 函数名相同,但参数不同,此时不论基类有无Virtual关键字,基类函数将被隐藏。
     2、 函数名相同,参数也相同,但基类无Virtual关键字(有就是覆盖),基类函数将被隐藏

所谓“隐藏”不是说不能调用,而是说,当调用y.f( )时调用的是Y中定义的新f( ),想调用基类的f则要显式说明y.X::f( ),显式说明而已。

3   所有构造函数、析构函数、operator=都不能自动继承 ,但编译器会自动生成默认构造函数、拷贝构造函数、operator=,并正确地调用基类的相应函数,它们工作的很好

   

     如果要为子类定义带参数的构造函数,则必须同时也定义子类的默认构造函数。如果自定义了拷贝构造函数,则也必须同时自定义默认构造函数

在子类的拷贝构造函数中,如果想调用基类的拷贝构造函数,必须显式在初始化列表调用,否则编译器自动调用默认构造函数

在子类的operator=中,如果想调用基类的operator=必须显式在函数体中调用,否则编译器什么都不做。

 

#include <iostream>
using namespace std;

//继承问题!
class A
{
public:
    A(
int i = 0){cout<<"A is doing"<<endl;};
    A(
const A& i){cout<<"A Copy is doing"<<endl;};
    
void print(void)
    
{
        cout
<<"A cout"<<endl;
    }

}
;

class B
{
public:
    B(
int i = 0){cout<<"B is doing"<<endl;};
    B(
const B& i){cout<<"B Copy is doing"<<endl;};
}
;

class C : public A  //继承类
{
    B b;    
//组合类
public:
    
//初始化语法:对于基类,使用类名调用构造函数;对于成员类,使用对象名调用构造函数
    C(int i = 0):b(i), A(i) {cout<<"C is doing"<<endl;};
//     C(int i = 0):A(i),b(i) {cout<<"C is doing"<<endl;};
//     C(int i = 0):b(i) {cout<<"C is doing"<<endl;};
//     C(int i = 0):A(i) {cout<<"C is doing"<<endl;};
//     C(int i = 0) {cout<<"C is doing"<<endl;};
    C(const C& i):A(i), b(i.b){cout<<"C Copy is doing"<<endl;};  
    
//这地方要显式的调用基类的拷贝构造函数,否则编译器调用了基类的缺省构造函数!
    
//这地方如果不指明调用B的拷贝构造函数,编译器会调用B的不带参数的缺省构造,很明显!
    void print(void)
    
{
        cout
<<"C cout"<<endl;
    }

}
;

int main()
{
    C c(
2);                    //构造顺序是A B C  
//     c.A::print();
//     c.C::print();
    C d=c;
    
//d.A::print();
    return 0;
}

这个程序有几个点:

1 首先,不管C类的构造函数怎么写,初始化列表或者怎么调用,怎么个顺序,各个类的构造顺序均不变,为A B C (基类, 组合类, 子类)

C(int i = 0):b(i), A(i) {cout<<"C is doing"<<endl;};

//  C(int i = 0):A(i)b(i) {cout<<"C is doing"<<endl;};

//  C(int i = 0):b(i) {cout<<"C is doing"<<endl;};

//  C(int i = 0):A(i) {cout<<"C is doing"<<endl;};

//  C(int i = 0) {cout<<"C is doing"<<endl;};

2,如果不显式的调用b的拷贝构造函数,编译器便会调用b的默认构造函数这很好理解,如果不显式调用A的拷贝构造函数,编译器将会调用A的默认构造函数!

3,如果A或者B没有自己定义的拷贝构造函数,C如果显式调用他们的拷贝构造调用的是编译器合成的拷贝构造函数。如果C没有定义拷贝构造函数,,编译器的合成拷贝构造函数会调用B的拷贝构造,因为编译器合成的拷贝构造是将内部成员依次拷贝。所以此时也会先调用A的拷贝构造,因为这个合成的拷贝构造函数会显式的调用它。

  

 

 

【上篇】
【下篇】

抱歉!评论已关闭.