C++ 继承
在本教程中,我们将借助示例了解 C++ 中的继承。
继承是 C++ 面向对象编程的关键特性之一。它允许我们从现有类(基类)创建一个新类(派生类)。
派生类继承了基类的特性,并且可以拥有自己的附加特性。例如,
class Animal {
// eat() 方法
// sleep() 方法
};
class Dog : public Animal {
// bark() 方法
};
在这里, Dog
类是从 Animal
类派生的。由于 Dog
派生自 Animal
, Dog
就继承了 Animal
的成员(方法和属性)。
请注意在 Dog
从 Animal
继承时使用了 public
关键字。
class Dog : public Animal {...};
我们也可以使用关键字 private
和 protected
代替 public
。我们将在本教程的后面学习 private
, public
和 protected
之间的差异。
is-a 关系
继承是一种 is-a 关系。仅当两个类之间存在 is-a 关系时才使用继承。
这里有些例子:
- 汽车是一种交通工具。
- 橙子是一种水果。
- 外科医生是医生。
- 狗是一种动物。
示例 1:C++ 继承的简单示例
本程序演示了 C++ 中的继承。
#include <iostream>
using namespace std;
// 基类
class Animal {
public:
void eat() {
cout << "I can eat!" << endl;
}
void sleep() {
cout << "I can sleep!" << endl;
}
};
// 子类
class Dog : public Animal {
public:
void bark() {
cout << "I can bark! Woof woof!!" << endl;
}
};
int main() {
Dog dog1;
// 调用基类中的方法
dog1.eat();
dog1.sleep();
// 调用自己的方法
dog1.bark();
return 0;
}
输出
I can eat!
I can sleep!
I can bark! Woof woof!!
这里,dog1
可以访问基类 Animal
的成员。这是因为 Dog
继承自 Animal
.
// Calling members of the Animal class
dog1.eat();
dog1.sleep();
C++ protected
成员
当涉及到 C++ 继承时,访问修饰符 protected
尤其重要。
与 private
成员一样, protected
成员在类之外是不可访问的。但是,它们可以被派生类和友元类/函数访问。
如果我们想隐藏类的数据,但仍然希望该数据被其派生类继承,我们就需要 protected
成员。
要了解有关 protected
的更多信息,请参阅我们的C++ 访问修饰符教程。
示例 2:C++ protected 成员
本程序演示了 C++ 继承中的受保护成员,演示了 protected
访问修饰符的用法。
#include <iostream>
#include <string>
using namespace std;
// base class
class Animal {
private:
string color;
protected:
string type;
public:
void eat() {
cout << "I can eat!" << endl;
}
void sleep() {
cout << "I can sleep!" << endl;
}
void setColor(string clr) {
color = clr;
}
string getColor() {
return color;
}
};
// derived class
class Dog : public Animal {
public:
void setType(string tp) {
type = tp;
}
void displayInfo(string c) {
cout << "I am a " << type << endl;
cout << "My color is " << c << endl;
}
void bark() {
cout << "I can bark! Woof woof!!" << endl;
}
};
int main() {
// Create object of the Dog class
Dog dog1;
// Calling members of the base class
dog1.eat();
dog1.sleep();
dog1.setColor("black");
// Calling member of the derived class
dog1.bark();
dog1.setType("mammal");
// Using getColor() of dog1 as argument
// getColor() returns string data
dog1.displayInfo(dog1.getColor());
return 0;
}
输出
I can eat!
I can sleep!
I can bark! Woof woof!!
I am a mammal
My color is black
这里,变量 type
是 protected
,因此可以从派生类 Dog
访问。我们可以看到这一点,因为我们已经使用函数在 Dog
类中的 setType()
方法中进行了 type
初始化。
另一方面,不能在 Dog
中使用 private
变量 color
。
class Dog : public Animal {
public:
void setColor(string clr) {
// Error: member "Animal::color" is inaccessible
color = clr;
}
};
此外,由于 protected
关键字隐藏了数据,我们无法在外部直接访问来自 Dog
或 Animal
类的 type
。
// Error: member "Animal::type" is inaccessible
dog1.type = "mammal";
C++ 继承中的访问模式
在我们之前的教程中,我们了解了 C++ 访问说明符,例如 public
、private
和 protected
。
到目前为止,我们已经使用 public
关键字从先前存在的基类继承了一个类。但是,我们也可以使用 private
and protected
关键字来继承类。例如,
class Animal {
// code
};
class Dog : private Animal {
// code
};
class Cat : protected Animal {
// code
};
我们可以派生类的各种方式被称为访问模式。这些访问模式具有以下效果:
- public: 如果派生类是在
public
模式中声明的,那么基类的成员会被派生类继承。 - private: 在这种情况下,基类的所有成员都成为派生类的
private
成员。 - 保护: 在这种情况下,基类的
public
成员成为派生类的protected
成员。
基类的private
成员在派生类中总是 private
的。
要了解更多信息,请访问我们的C++ 公共、私有、受保护的继承教程。
继承中的成员函数覆盖
假设基类和派生类具有相同名称和参数的成员函数。
如果我们创建了派生类的对象并尝试访问该成员函数,则会调用派生类中的成员函数而不是基类中的成员函数。
这种情况下,派生类的成员函数覆盖了基类的成员函数。
了解有关C++ 中函数覆盖的更多信息。