C++ 类和对象 (下)
在前面的部分中,我们已经介绍了C++中的类与对象的基本概念,包括类的定义、构造函数、析构函数以及成员函数的使用。本节将进一步深入,介绍C++中类与对象的高级特性,如继承、多态、友元函数、静态成员以及一些实际的编程实例。我们将通过具体的代码示例帮助读者更好地理解和掌握这些概念。
1. 继承
继承是面向对象编程的重要特性之一。通过继承,类可以共享和重用父类的属性和方法,同时还可以在子类中添加或修改其功能。
1.1 继承的基本概念
在C++中,继承允许我们创建一个新的类,该类是基于已有类(称为父类或基类)的一种扩展。子类继承了父类的成员变量和成员函数,并且可以重写父类的成员函数或者添加新的成员。
基本语法
cppCopy Codeclass 子类名 : 访问控制方式 基类名 {
// 子类的成员变量和成员函数
};
1.2 继承的访问控制
C++支持三种继承方式:
- 公有继承(public inheritance):子类可以继承父类的公有和保护成员,而父类的私有成员无法被继承。
- 保护继承(protected inheritance):子类可以继承父类的公有、保护成员,但私有成员依然不可继承。
- 私有继承(private inheritance):子类只能访问父类的公有和保护成员,但在子类外部无法直接访问这些继承的成员。
1.3 示例:公有继承
以下是一个简单的示例,演示如何通过继承创建一个子类,并使用从父类继承的成员。
cppCopy Code#include <iostream>
using namespace std;
// 基类:Animal
class Animal {
public:
Animal(string n) : name(n) {}
void speak() const {
cout << name << " makes a sound." << endl;
}
private:
string name;
};
// 派生类:Dog
class Dog : public Animal {
public:
Dog(string n) : Animal(n) {}
void speak() const {
cout << "Woof! I am a dog." << endl;
}
};
int main() {
Dog dog("Buddy");
dog.speak(); // 输出 "Woof! I am a dog."
return 0;
}
在这个例子中,Dog
类继承自Animal
类。虽然Animal
类有一个speak()
函数,但我们在Dog
类中重写了speak()
函数,提供了一个更具体的实现。
2. 多态
多态是面向对象程序设计的另一个核心特性,它允许不同的对象调用同一接口(方法),但根据对象的类型,表现出不同的行为。C++支持两种类型的多态:静态多态(函数重载和运算符重载)和动态多态(虚函数)。
2.1 静态多态
静态多态通常通过函数重载和运算符重载来实现。编译器根据函数调用时传入的参数类型来确定调用哪个版本的函数。
示例:函数重载
cppCopy Code#include <iostream>
using namespace std;
class Printer {
public:
void print(int i) {
cout << "Printing integer: " << i << endl;
}
void print(double d) {
cout << "Printing double: " << d << endl;
}
};
int main() {
Printer printer;
printer.print(10); // 输出 "Printing integer: 10"
printer.print(3.14); // 输出 "Printing double: 3.14"
return 0;
}
在这个例子中,Printer
类有两个print()
函数,一个接受整数类型,另一个接受浮点数类型。编译器会根据传入的参数类型来选择合适的重载版本。
2.2 动态多态
动态多态通常通过虚函数(virtual function)来实现。虚函数使得C++在运行时可以根据对象的实际类型来调用相应的方法,而不是编译时决定。
示例:虚函数与动态绑定
cppCopy Code#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() const {
cout << "Drawing a shape." << endl;
}
};
class Circle : public Shape {
public:
void draw() const override {
cout << "Drawing a circle." << endl;
}
};
class Square : public Shape {
public:
void draw() const override {
cout << "Drawing a square." << endl;
}
};
int main() {
Shape* shape;
Circle circle;
Square square;
shape = &circle;
shape->draw(); // 输出 "Drawing a circle."
shape = □
shape->draw(); // 输出 "Drawing a square."
return 0;
}
在这个例子中,Shape
类定义了一个虚函数draw()
,并且Circle
和Square
类都重写了这个函数。通过使用虚函数,C++能够在运行时根据shape
指针指向的对象类型来调用对应的draw()
函数。
2.3 虚函数的作用
虚函数使得多态成为可能。它允许程序在运行时决定调用哪个类的函数,从而提高了代码的灵活性和可扩展性。
3. 友元函数
在C++中,友元函数(friend function)是指一个可以访问类的私有成员和保护成员的函数。友元函数不是类的成员函数,但它被声明为类的朋友,因此可以访问类的私有成员。
3.1 友元函数的基本语法
cppCopy Codeclass 类名 {
friend 返回类型 函数名(参数列表);
};
3.2 示例:友元函数
cppCopy Code#include <iostream>
using namespace std;
class Box {
private:
double length;
public:
Box(double l) : length(l) {}
friend void printLength(const Box& b); // 声明友元函数
};
void printLength(const Box& b) {
cout << "The length of the box is: " << b.length << endl; // 可以访问私有成员
}
int main() {
Box box(5.5);
printLength(box); // 输出 "The length of the box is: 5.5"
return 0;
}
在这个例子中,printLength()
是Box
类的友元函数,因此可以访问Box
类的私有成员length
。
4. 静态成员
静态成员是类级别的成员,而不是对象级别的成员。静态成员可以被类的所有对象共享,并且它不属于任何一个具体的对象。
4.1 静态成员变量
静态成员变量在类的所有对象之间共享,因此每个对象都会看到相同的静态成员。
示例:静态成员变量
cppCopy Code#include <iostream>
using namespace std;
class Counter {
private:
static int count; // 静态成员变量
public:
Counter() {
count++;
}
static int getCount() { // 静态成员函数
return count;
}
};
int Counter::count = 0; // 静态成员变量的定义和初始化
int main() {
Counter c1, c2, c3;
cout << "Total objects created: " << Counter::getCount() << endl; // 输出 3
return 0;
}
在这个例子中,Counter
类有一个静态成员变量count
,用于记录创建的Counter
对象的数量。静态成员变量在所有对象之间共享,因此它能够跟踪所有对象的总数。
4.2 静态成员函数
静态成员函数只能访问静态成员变量和静态成员函数。它不能访问类的非静态成员变量和非静态成员函数。
5. 构造函数与析构函数的高级用法
5.1 构造函数的委托
C++11引入了构造函数的委托(constructor delegation)功能,允许一个构造函数调用另一个构造函数,以减少重复代码。
示例:构造函数委托
cppCopy Code#include <iostream>
using namespace std;
class Rectangle {
private:
int width, height;
public:
Rectangle() : Rectangle(1, 1) {} // 委托给另一个构造函数
Rectangle(int w, int h) : width(w), height(h) {}
void display() {
cout << "Width: " << width << ", Height: " << height << endl;
}
};
int main() {
Rectangle r1; // 默认构造
r1.display(); // 输出 "Width: