面向对象(二)

面向对象(二)

在上一篇文章 面向对象(一) | 四叶草の博客 (wzcwzc.cool) 中,我们介绍了面向对象的基本概念,以及C++中类和对象的基础知识。在这篇文章中,我们将深入探讨C++面向对象编程的其他重要特性,包括继承、多态和运算符重载。

一、继承

继承是面向对象编程的一个核心概念,它允许我们创建一个新类,继承并重用现有类的属性和方法。这样,新类可以基于现有类进行扩展,而无需从头开始。

1. 基类 & 派生类

  • 基类:被继承的类称为基类、父类或超类。
  • 派生类:执行继承操作的类称为派生类或子类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class BaseClass {
public:
int baseVar;
void baseFunc() {
cout << "Function in Base Class" << endl;
}
};

class DerivedClass: public BaseClass {
public:
int derivedVar;
void derivedFunc() {
cout << "Function in Derived Class" << endl;
}
};

在上述代码中,DerivedClass 是从 BaseClass 派生出来的。这意味着 DerivedClass 继承了 BaseClass 的所有属性和方法。

2. 访问控制与继承

继承时,基类中的成员有可能在派生类中改变其访问属性:

  • 基类中的 public 成员在派生类中仍然是 public
  • 基类中的 protected 成员在派生类中仍然是 protected
  • 基类中的 private 成员不能直接被派生类访问,但可以通过基类的公共和保护成员函数访问。

二、多态

多态意味着调用成员函数时,会执行与该函数在其所属对象类中的定义相对应的版本。

1. 虚函数

为了实现运行时多态,我们使用虚函数。一个类成员函数的声明前加上关键字 virtual,它就变成了虚函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Base {
public:
virtual void show() {
cout << "Base class's show." << endl;
}
};

class Derived: public Base {
public:
void show() {
cout << "Derived class's show." << endl;
}
};

2. 纯虚函数

纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。声明纯虚函数的方法是在函数声明的结尾放置 = 0

1
2
3
4
class Base {
public:
virtual void show() = 0; // 纯虚函数
};

三、运算符重载

C++允许在类中重定义或重载大部分的内置运算符。这样,我们可以为用户自定义的数据类型提供自然的操作方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Complex {
private:
float real;
float imag;
public:
Complex(): real(0), imag(0) { }
Complex operator + (Complex const &obj) {
Complex temp;
temp.real = real + obj.real;
temp.imag = imag + obj.imag;
return temp;
}
void display() {
cout << real << " + i" << imag << endl;
}
};

在上述代码中,我们重载了 + 运算符,使其可以用于 Complex 类型的对象。

四、友元

在C++中,友元(friend)是一种特殊的机制,使得一个函数或者类可以访问另一个类的私有或保护成员。这对于一些特定的设计模式和库功能是必要的,尽管在常规类设计中不鼓励频繁使用友元功能,因为它违反了封装原则。

1. 友元函数

  1. 友元函数定义: 友元函数不是该类的成员函数,但可以访问类的私有和保护成员。
  2. 如何声明:在类定义中使用关键字 friend

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cppCopy codeclass Box {
private:
double width;
public:
friend void printWidth(Box box);
void setWidth(double wid) {
width = wid;
}
};

// 注意: printWidth() 不是任何类的成员函数
void printWidth(Box box) {
/* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
cout << "Width of box : " << box.width << endl;
}

int main() {
Box box;

// 使用成员函数设置宽度
box.setWidth(10.0);

// 使用友元函数输出宽度
printWidth(box);

return 0;
}

2. 友元类

不仅可以声明函数为友元,还可以声明整个类为另一个类的友元。这意味着友元类的所有成员函数都可以访问另一个类的私有和保护成员。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cppCopy codeclass ClassA {
private:
int value;
public:
ClassA() : value(5) {}
friend class ClassB; // ClassB是ClassA的友元类
};

class ClassB {
public:
void showA(ClassA& a) {
cout << "ClassA value: " << a.value << endl;
}
};

int main() {
ClassA a;
ClassB b;
b.showA(a);
return 0;
}

在使用友元时需要谨慎,因为它可能会导致数据不一致或意外的副作用。它的使用应该是基于特定的需求,而不是常规设计的一部分。

五、总结

面向对象的编程方法为C++提供了强大的工具和技术,使得代码更加模块化、可重用和易于维护。通过继承、多态和运算符重载,我们可以创建更加复杂和功能丰富的程序。

希望这两篇文章能帮助你更好地理解和使用C++的面向对象特性。