C++ 类和对象 (下)

在前面的部分中,我们已经介绍了C++中的类与对象的基本概念,包括类的定义、构造函数、析构函数以及成员函数的使用。本节将进一步深入,介绍C++中类与对象的高级特性,如继承、多态、友元函数、静态成员以及一些实际的编程实例。我们将通过具体的代码示例帮助读者更好地理解和掌握这些概念。

1. 继承

继承是面向对象编程的重要特性之一。通过继承,类可以共享和重用父类的属性和方法,同时还可以在子类中添加或修改其功能。

1.1 继承的基本概念

在C++中,继承允许我们创建一个新的类,该类是基于已有类(称为父类或基类)的一种扩展。子类继承了父类的成员变量和成员函数,并且可以重写父类的成员函数或者添加新的成员。

基本语法

cppCopy Code
class 子类名 : 访问控制方式 基类名 { // 子类的成员变量和成员函数 };

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 = &square; shape->draw(); // 输出 "Drawing a square." return 0; }

在这个例子中,Shape类定义了一个虚函数draw(),并且CircleSquare类都重写了这个函数。通过使用虚函数,C++能够在运行时根据shape指针指向的对象类型来调用对应的draw()函数。

2.3 虚函数的作用

虚函数使得多态成为可能。它允许程序在运行时决定调用哪个类的函数,从而提高了代码的灵活性和可扩展性。

3. 友元函数

在C++中,友元函数(friend function)是指一个可以访问类的私有成员和保护成员的函数。友元函数不是类的成员函数,但它被声明为类的朋友,因此可以访问类的私有成员。

3.1 友元函数的基本语法

cppCopy Code
class 类名 { 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: