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=拷贝或者赋值给基类对象。但是虽然用派生类对象初始化基类对象,但是基类对象只能调用基类的成员函数,而不能访问派生类的成员函数。