继承是 C++ 面向对象编程的关键特性之一。它允许我们从现有类(基类)创建一个新类(派生类)。
派生类继承了基类的特性,并且可以拥有自己的附加特性。例如,
C++ 等面向对象编程语言的主要特性之一是数据隐藏。数据隐藏是指限制对类的数据成员的访问。这是为了防止其他函数和类篡改类数据。但是,让一些成员函数和成员数据可访问也很重要,以便可以间接操作隐藏的数据。C++ 的访问修饰符允许我们确定哪些类成员可以被其他类和函数访问,哪些不能。
public 关键字用于创建公共成员(数据和函数)。公共成员可以从程序的任何部分访问。
private 关键字用于创建私有成员(数据和函数)。私有成员只能从类内部访问。但是,友元类和友元函数可以访问私有成员。
protected 关键字用于创建受保护的成员(数据和函数)。可以在类内和派生类中访问受保护的成员。
数据隐藏是面向对象编程的一个基本概念。它限制了来自类外部的私有成员的访问。同样,受保护的成员只能由派生类访问,而不能从外部访问。例如,
然而,C++ 中有一个叫做友元函数的特性,它打破了这个规则,允许我们从类外部访问成员函数。同样,还有一个朋友类。
友元函数可以访问类的私有和受保护数据。我们在类的主体内使用friend关键字声明了一个friend函数。
类的友元函数在该类的范围之外定义,但它有权访问该类的所有私有成员和受保护成员。即使友元函数的原型出现在类定义中,友元函数也不是成员函数。
友元可以是函数、函数模板、成员函数、类或类模板,在这种情况下,整个类及其所有成员都是友元。
#include <iostream> using namespace std; class complex { public: complex(float real_v, float imag_v): real(real_v), imag(imag_v){}; complex operator=(complex a) {real=a.real; imag=a.imag; return *this;}; // friend function friend complex operator+(complex a, complex b); friend void show_complex(complex a); private: float real; float imag; }; complex operator+(complex a, complex b) { complex c(0,0); c.real = a.real + b.real; c.imag = a.imag + b.imag; return c; } void show_complex(complex a) { cout << "(" << a.real << "," << a.imag << ")" << endl; } int main() { complex num1(1.05, 20.6); complex num2(10.0, 15.9); cout << "num1 : "; show_complex(num1); cout << "num2 : "; show_complex(num2); cout << "sum : "; complex sum = num1+num2; show_complex(sum); return 0; } 输出结果 num1 : (1.05,20.6) num2 : (10,15.9) sum : (11.05,36.5)
在C++中,我们还可以使用友类。
当一个类被声明为友类时,友类的所有成员函数都成为友函数。
在下列的例子中,Algo是一个友类,我们可以从Algo内部访问Complex的所有成员。
但是,我们无法从Complex内部访问Algo的成员。这是因为 C++ 中的友关系是单向。
#include <iostream> using namespace std; class Algo; class Complex { private: int real; int imag; // friend class declaration friend class Algo; public: Complex()=delete; Complex(int rv, int iv): real(rv), imag(iv) {}; }; class Algo { private: int numB; public: Algo() : numB(1) {} int add(Complex obj) { return obj.real + numB; } int sub(Complex obj) { return obj.real - numB; } }; int main() { Algo objAlgo; Complex objA(10, 35); Complex objB(5, 10); cout << " Sum: " << objAlgo.add(objA) << endl; cout << "diff: " << objAlgo.sub(objB) << endl; return 0; } 输出结果 Sum: 11 diff: 4
一个类可以从多个类派生,这意味着,它可以从多个基类继承数据和函数。要定义派生类,我们使用类派生列表来指定基类。类派生列表命名一个或多个基类并具有以下形式
class derived-class: access-specifier base-class
其中 access-specifier 是 public、protected 或 private 之一,base-class 是先前定义的类的名称。如果未使用访问说明符,则默认情况下它是private。
派生类可以访问其基类的所有非私有成员。因此,派生类的成员函数不应访问的基类中的私有成员。
访问 | public | protected | private |
---|---|---|---|
相同类 | 是 | 是 | 是 |
派生类 | 是 | 是 | 否 |
外部类 | 是 | 否 | 否 |
派生类继承所有基类方法,但下例的方法除外
当从基类派生类时,可以通过public、protected 或 private来继承基类。继承的类型由上面解释的访问说明符指定。
我们很少使用受保护或私有继承,但通常使用公共继承。在使用不同类型的继承时,遵守下列规则