C++中的继承public, protected和private
C++访问修饰符
继承是 C++ 面向对象编程的关键特性之一。它允许我们从现有类(基类)创建一个新类(派生类)。
派生类继承了基类的特性,并且可以拥有自己的附加特性。例如,
C++ 等面向对象编程语言的主要特性之一是数据隐藏。数据隐藏是指限制对类的数据成员的访问。这是为了防止其他函数和类篡改类数据。但是,让一些成员函数和成员数据可访问也很重要,以便可以间接操作隐藏的数据。C++ 的访问修饰符允许我们确定哪些类成员可以被其他类和函数访问,哪些不能。
public访问修饰符
public 关键字用于创建公共成员(数据和函数)。公共成员可以从程序的任何部分访问。
private访问修饰符
private 关键字用于创建私有成员(数据和函数)。私有成员只能从类内部访问。但是,友元类和友元函数可以访问私有成员。
protected 访问修饰符
protected 关键字用于创建受保护的成员(数据和函数)。可以在类内和派生类中访问受保护的成员。
C++友函数和友类
数据隐藏是面向对象编程的一个基本概念。它限制了来自类外部的私有成员的访问。同样,受保护的成员只能由派生类访问,而不能从外部访问。例如,
然而,C++ 中有一个叫做友元函数的特性,它打破了这个规则,允许我们从类外部访问成员函数。同样,还有一个朋友类。
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++的友类
在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来继承基类。继承的类型由上面解释的访问说明符指定。
我们很少使用受保护或私有继承,但通常使用公共继承。在使用不同类型的继承时,遵守下列规则
- public 公共继承 - 使用public派生基类时,基类的公共成员(public)成为派生类的公共成员(public),基类的受保护成员(protected)成为派生类的受保护成员(protected),基类的私有成员不能直接从派生类访问,但可以通过调用基类的公共成员和受保护成员来访问。
- protected 受保护的继承 - 使用protected派生基类时,基类的公共成员(public)和受保护成员(protected)成为派生类的受保护成员(protected)。
- private 私有继承 - 使用private派生基类时,基类的公共成员和受保护成员成为派生类的私有成员(private)。