c++++的继承机制通过派生类继承基类的成员实现代码重用和多态性,使用冒号指定继承方式,其中public继承保持基类成员访问权限不变,protected继承将基类public成员变为protected,private继承将基类public和protected成员均变为private,基类private成员在派生类中不可直接访问;多态通过虚函数实现,允许基类指针或引用调用派生类重写的虚函数,从而实现运行时动态绑定;多重继承允许一个类继承多个基类,但可能引发菱形继承问题,可通过虚继承解决,但会增加复杂性和性能开销,因此建议优先使用组合而非多重继承。

C++的继承机制允许你创建一个新类(派生类),它继承了现有类(基类)的特性。这不仅节省了代码,还实现了代码重用和多态性。理解基类和派生类的访问权限是掌握继承的关键。
解决方案
C++通过使用冒号
:来实现继承。基本的语法如下:
立即学习“C++免费学习笔记(深入)”;
class 派生类名 : 访问修饰符 基类名 {
// 派生类的成员
};其中,
访问修饰符可以是
public、
protected或
private。 这个修饰符决定了基类成员在派生类中的访问权限。
访问权限详解:
public
继承: 基类的public
成员在派生类中仍然是public
,基类的protected
成员在派生类中仍然是protected
,基类的private
成员在派生类中不可直接访问(但可以通过基类的public
或protected
成员函数访问)。 这通常是希望派生类完全拥有基类的接口时使用的。protected
继承: 基类的public
成员在派生类中变成protected
,基类的protected
成员在派生类中仍然是protected
,基类的private
成员在派生类中不可直接访问。protected
继承通常用于希望基类的接口对派生类的进一步派生类可用,但不想暴露给外部用户的情况。private
继承: 基类的public
成员在派生类中变成private
,基类的protected
成员在派生类中变成private
,基类的private
成员在派生类中不可直接访问。private
继承是最严格的继承方式,基类的接口完全被隐藏在派生类内部。
示例代码:
#includeclass Base { public: int publicVar; protected: int protectedVar; private: int privateVar; public: Base(int a, int b, int c) : publicVar(a), protectedVar(b), privateVar(c) {} void printBase() { std::cout << "Base: public=" << publicVar << ", protected=" << protectedVar << std::endl; // 无法访问 privateVar,除非通过成员函数 } int getPrivateVar() const { return privateVar; } // 提供一个访问私有成员的接口 }; class PublicDerived : public Base { public: PublicDerived(int a, int b, int c) : Base(a, b, c) {} void printDerived() { std::cout << "PublicDerived: public=" << publicVar << ", protected=" << protectedVar << std::endl; //std::cout << "PublicDerived: private=" << privateVar << std::endl; // 错误:无法访问基类的私有成员 } }; class ProtectedDerived : protected Base { public: ProtectedDerived(int a, int b, int c) : Base(a, b, c) {} void printDerived() { std::cout << "ProtectedDerived: public=" << publicVar << ", protected=" << protectedVar << std::endl; } }; class PrivateDerived : private Base { public: PrivateDerived(int a, int b, int c) : Base(a, b, c) {} void printDerived() { std::cout << "PrivateDerived: public=" << publicVar << ", protected=" << protectedVar << std::endl; } }; int main() { PublicDerived pub(1, 2, 3); pub.printDerived(); std::cout << "Main (PublicDerived): public=" << pub.publicVar << std::endl; // 可以访问 publicVar ProtectedDerived pro(4, 5, 6); pro.printDerived(); //std::cout << "Main (ProtectedDerived): public=" << pro.publicVar << std::endl; // 错误:publicVar 在这里是不可访问的 PrivateDerived pri(7, 8, 9); pri.printDerived(); //std::cout << "Main (PrivateDerived): public=" << pri.publicVar << std::endl; // 错误:publicVar 在这里是不可访问的 Base base(10,11,12); std::cout << "Base private variable: " << base.getPrivateVar() << std::endl; // 通过公共接口访问私有成员 return 0; }
为什么需要继承?继承解决了什么问题?
继承的核心目的是代码重用和实现多态。想象一下,如果没有继承,你需要为每个相似的类编写几乎相同的代码。继承允许你创建一个通用的基类,然后通过派生类来扩展和修改其行为,避免代码冗余。多态性则允许你使用基类的指针或引用来操作派生类的对象,从而实现更灵活的设计。例如,你可以有一个
Animal基类,然后有
Dog和
Cat派生类。你可以创建一个
Animal指针数组,其中存储
Dog和
Cat对象,并调用它们的
makeSound()方法,而不需要知道它们具体的类型。
虚函数在继承中的作用是什么?如何实现多态?
虚函数是实现多态的关键。 在一个基类中声明为
virtual的函数,可以在派生类中被重写(override)。当通过基类的指针或引用调用虚函数时,实际执行的是派生类中的版本(如果派生类重写了该函数)。
#includeclass Animal { public: virtual void makeSound() { std::cout << "Generic animal sound" << std::endl; } }; class Dog : public Animal { public: void makeSound() override { std::cout << "Woof!" << std::endl; } }; class Cat : public Animal { public: void makeSound() override { std::cout << "Meow!" << std::endl; } }; int main() { Animal* animals[3]; animals[0] = new Animal(); animals[1] = new Dog(); animals[2] = new Cat(); for (int i = 0; i < 3; ++i) { animals[i]->makeSound(); // 调用的是实际对象的 makeSound() 方法 delete animals[i]; } return 0; }
在这个例子中,尽管我们使用的是
Animal指针,但
makeSound()函数的行为会根据实际对象的类型而改变。这就是多态的威力。
多重继承是什么?它有哪些潜在的问题?
多重继承是指一个类可以同时继承多个基类。虽然这提供了更大的灵活性,但也可能导致一些问题,比如菱形继承(Diamond Problem)。菱形继承指的是一个类
D同时继承了
B和
C,而
B和
C又都继承自
A。 如果
A中有一个成员变量,那么
D中就会有两个
A的实例,这可能会导致二义性和不必要的内存消耗。
为了解决菱形继承的问题,可以使用虚继承。虚继承确保在继承链中只有一个基类的实例。
#includeclass A { public: int data; }; class B : virtual public A {}; class C : virtual public A {}; class D : public B, public C { public: void setData(int value) { A::data = value; // 只有一个 A 的实例,所以没有二义性 } int getData() { return A::data; } }; int main() { D d; d.setData(10); std::cout << "Data: " << d.getData() << std::endl; return 0; }
尽管虚继承解决了菱形继承的问题,但它也增加了代码的复杂性,并且可能会影响性能。因此,在设计类层次结构时,应该谨慎使用多重继承。 尽量使用组合(Composition)来代替继承,除非确实需要继承所提供的多态性。










