?
目录
C++中的继承和模板是非常强大和灵活的特性,它们可以帮助我们实现代码复用、抽象和泛化等目标。本文将着重介绍私有继承、多重继承和类模板这三个C++中比较重要的特性。
私有继承是一种比较特殊的继承方式,它在语法上与公有继承和保护继承没有太大区别,但是其继承关系所暴露的接口和成员变量都会被隐藏起来,只有派生类自己可以访问到基类的成员。在使用私有继承时,我们通常会借助基类指针或引用来访问基类的成员,而不会直接使用派生类对象。
私有继承的应用场景比较广泛,例如可以用来实现“has-a”关系、模块化设计等。具体来说,如果一个类需要另一个类的部分功能,但是不想公开其接口,可以使用私有继承。此外,私有继承也可以用来防止基类的成员被误操作或滥用,从而提高代码的安全性。
多重继承是C++中比较复杂和容易出现问题的特性之一,它允许一个派生类同时继承多个基类。多重继承在语法上并不复杂,但是在设计和实现上需要考虑一些问题,例如可能会出现菱形继承问题、基类构造函数的调用顺序等。因此在使用多重继承时需要谨慎考虑其适用性和实现细节。
多重继承的应用场景也比较广泛,例如可以用来实现多态、功能组合等。具体来说,如果一个类需要具有多种不同的特性或行为,可以使用多重继承来组合多个基类。此外,多重继承也可以用来实现接口继承和实现继承的分离,从而更好地实现面向对象的编程思想。
类模板是C++中非常强大和灵活的特性,它允许我们通过一个通用的模板来生成多个具体的类。类模板在定义时需要指定模板参数,这些参数可以是类型、常量、模板等等。类模板可以用来实现泛型编程、容器和算法库等。
类模板的语法比较复杂,但是理解一些基本概念后就可以轻松地应用它们。例如,我们可以使用模板参数来定义成员变量和成员函数,或者使用特化(partial specialization)和偏特化(full specialization)来针对不同的情况实现不同的行为。此外,C++11及以上版本还提供了可变参数模板(variadic template)和模板别名(template alias)等新特性,使得类模板的应用更加灵活和便捷。
?
私有继承是指派生类以 private 访问权限继承基类的成员。这意味着派生类无法直接访问基类的成员,只能通过基类指针或引用来访问。
#include <iostream>
class Base {
public:
void display() {
std::cout << "Base class" << std::endl;
}
};
class Derived : private Base {
public:
void showMessage() {
display(); // 通过基类指针访问基类的成员函数
}
};
int main() {
Derived derived;
derived.showMessage();
return 0;
}
在这个示例中,Derived
类私有继承 Base
类。Derived
类中的 showMessage()
函数通过基类指针调用了 Base
类的 display()
函数。
Base class
私有继承主要用于实现类与类之间的“has-a”关系,即一个类包含另一个类的对象作为其成员。
多重继承是指派生类可以同时继承多个基类。在多重继承中,派生类可以分别指定不同的继承方式(public、protected 或 private)来控制基类成员的访问权限。
下面是一个使用多重继承的示例代码:
#include <iostream>
class Base1 {
public:
void display1() {
std::cout << "Base1 class" << std::endl;
}
};
class Base2 {
public:
void display2() {
std::cout << "Base2 class" << std::endl;
}
};
class Derived : public Base1, private Base2 {
public:
void showMessage() {
display1(); // 通过派生类直接访问公有基类的成员函数
//display2(); // 错误!无法直接访问私有基类的成员函数
}
};
int main() {
Derived derived;
derived.showMessage();
return 0;
}
在这个示例中,Derived
类同时继承了 Base1
和 Base2
两个基类。Derived
类中的 showMessage()
函数可以直接调用 Base1
类的 display1()
函数,但无法直接调用 Base2
类的 display2()
函数。
输出结果为:
Base1 class
类模板允许我们定义通用的类模板,在实例化时可以指定不同的类型、常量和模板参数。
下面是一个使用类模板的示例代码,实现了一个简单的栈(Stack)类模板:
#include <iostream>
#include <vector>
template <typename T>
class Stack {
private:
std::vector<T> elements;
public:
void push(const T& value) {
elements.push_back(value);
}
void pop() {
if (!elements.empty()) {
elements.pop_back();
}
}
T top() const {
if (!elements.empty()) {
return elements.back();
}
throw std::out_of_range("Stack is empty.");
}
bool empty() const {
return elements.empty();
}
};
int main() {
Stack<int> stack;
stack.push(1);
stack.push(2);
stack.push(3);
while (!stack.empty()) {
std::cout << stack.top() << " ";
stack.pop();
}
std::cout << std::endl;
return 0;
}
在这个示例中,Stack
是一个类模板,可以使用不同类型的数据来实例化。在 main()
函数中,我们使用 Stack<int>
来创建一个整数类型的栈,并依次将元素压入栈中,然后通过 top()
和 pop()
函数来访问和删除栈顶元素。
输出结果为
3 2 1
类模板可以实现更加灵活的泛型编程,通过指定模板参数来确定类模板中的具体类型、常量和模板参数。这使得类模板在STL(标准模板库)的容器类(如 vector
、list
、map
等)中得到了广泛应用。