C++ 继承

1. 隐藏

如果继承一个类并且对它的函数进行重新定义,可能会出现两种情况。

(1)在派生类中和基类定义的函数函数名,返回值和参数类型一致,这叫做函数的重定义

(2)如果基类的成员函数为虚函数,派生类定义的同名同参同返回值的函数叫做重写。

针对重定义,有如下代码:

class Base {
    public:
        void fun() const {
            cout << "Base :: fun()" << endl;
        } 
        void fun(int) {
            cout << "Base :: funn(int)" << endl;
        }
};
class Derived : public Base {
    public:
        void fun() {
            cout << "Derived :: fun()" << endl;
        }
};
int main(void) {
    Derived D;
    D.fun();
}
结果:

Derived :: fun()

在派生类Derived中公有继承了基类Base中的三个函数,并且重定义了void fun()函数。在main中实例化派生类对象D,用D调用void fun()时,结果调用的是Derived重定义的函数,而并没有调用Base的void fun(),因此在派生类重定义同名的fun函数时,基类fun函数包括重载的fun函数会被隐藏,如果想要调用基类的函数,加上基类作用域。

D.Base::fun();
// 结果
D.Base::fun();
如果基类定义一个与派生类重定义函数名不同的函数void gun(),并且派生类没有重定义,则派生类对象访问时gun()时,则调用基类的gun()。

2. 非自动继承的函数

(1)基类的构造函数和析构函数不能被继承。因为构造函数是用来创建对象,类中的其他成员函数(除静态成员函数)只能被对象调用,因为基类并不知道派生类有哪些数据成员,有哪些成员函数,构造函数只知道本层次的对象的数据及能够操作的成员函数。

(2)operator=也不能被继承。它完成了与构造函数类似的工作。

classBase {
    public:
        Base() {
            cout << "BaseConstructor" << endl;
        }
        int operator=(int a) {
            cout << "Baseoperator=" << endl;
            return a;
        }
        ~Base() {
            cout << "BaseDestructor" << endl;
        }
};
classDerived1 : public Base {};
intmain(void) {
    Derived1 A;
    A = 10;     
}

此时编译器会报错:

HIdden.cpp: In function ‘int main()’:
HIdden.cpp:38:7: error: no match for ‘operator=’ (operand types are ‘Derived1’ and ‘int’)
 A = 10;       ^
HIdden.cpp:38:7: note: candidate is:
HIdden.cpp:21:7: note: Derived1& Derived1::operator=(const Derived1&)
class Derived1 : public Base {};       ^
HIdden.cpp:21:7: note:   no known conversion for argument 1 from ‘int’ to ‘const Derived1&’

在派生类Derived1中,没有定义与基类同名同参同返回值的operator,如果operator=被继承了,即使没有重定义,也会调用基类的operator=。但是编译器报错,说明operator=并不能被继承。

但有如下情况:

class Base {
    public:
        Base() {
            cout << "Base Constructor" << endl;
        }
        Base & operator=(const Base & r) {
            cout << "Base::operator=" << endl;
            return *this;
        }
        ~Base() {
            cout << "Base Destructor" << endl;
        }
};
class Derived1 : public Base {};
class Derived2 : public Base {
    public:
        Derived2() {
            cout << "Derived2 Constructor" << endl;
        }
        Derived2 & operator=(const Derived2 & r) {
            cout << "Derived2::operator=" << endl;
            return *this;
        }
        ~Derived2() {
            cout << "Derived2 Destructor" << endl;
        }
};
int main(void) {
    Derived1 A;
    Derived1 B;
    A = B;    
    Derived2 C;
    Derived2 D;
    C = D;   
}
运行结果如下:

Base Constructor
Base Constructor
Base::operator=
Base Constructor
Derived2 Constructor
Base Constructor
Derived2 Constructor
Derived2::operator=
Derived2 Destructor
Base Destructor
Derived2 Destructor
Base Destructor
Base Destructor
Base Destructor

Derived1是一个空类,并且默认是会有Derived1& operator=(constDerived1&),但进行赋值操作的时候应该会调用默认的operator=,但调用了Base的operator=,operator不是应该不会被继承吗?我是这样想的,Derived1的对象B赋值给Derived1的对象A,而且Derive1继承了Base,也就是说就算Base的数据成员为私有,Derived1不能访问,也会被继承到Derived1,所以赋值的时候也会对Base的数据成员进行赋值操作。会在默认的operator=有如下定义:

Derived1& Derived1::operator=(const Derived1 & r) {
    Base::operator=(r);
}

在派生类中调用基类的operator=,可以对基类数据进行赋值操作。所以在派生类没有定义operator=,而默认operator=就会调用基类operator=。在Derived2中定义了与默认operator=同名同参同返回值赋值运算符,没有调用Base的operator=。

3. 向上类型转换

<span style="font-size:10px;">class Base {
    public:
        Base():Data(0) {
            cout << "Base Constructor" << endl;
        }
        Base(const Base & r) {
            Data = r.Data;
            cout << "Base Copy Constructor" << endl;
        }
        Base & operator=(const Base & r) {
            Data = r.Data;
            cout << "Base operator=" << endl;
        }
    private:
        int Data;
};

class Derived : public Base {
    public:
        Derived(){
            cout << "Derived Constructor" << endl;
        }
        Derived(const Derived & r) {
            ch = r.ch;
            d  = r.d;
            cout << "Derived Copy Constructor" << endl;
        }
        Derived & operator=(const Derived & r) {
            ch = r.ch;
            d  = r.d;
            cout << "Derived Copy Constructor" << endl;
        }
        ~Derived() {
            cout << "Derived Destructor" << endl;
        }
    private:
        char   ch;
        double d;
};

int main(void) {

    Derived D;
    Base B(D);
    B = D;
}</span><strong style="font-size:14px;">
</strong>

结果如下:

BaseConstructor
DerivedConstructor
BaseCopy Constructor
Baseoperator=
Derived Destructor

派生类Derived实例化了一个对象D,基类Base实例化了一个对象B,并且用D初始化,但Base的拷贝构造的参数为Base类型,不是Derived类型。这就涉及到向上类型转换。

如上图所示,将派生类对象拷贝或者赋值给基类对象时,仅仅只会将派生类继承基类的数据成员通过基类的拷贝构造或者operator=拷贝或者赋值给基类对象。但是虽然用派生类对象初始化基类对象,但是基类对象只能调用基类的成员函数,而不能访问派生类的成员函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值