封装
C++的封装体现在类中。封装是指将数据和操作数据的函数绑定在一起,形成一个单元12。这样可以保护数据的安全性,防止被外部访问或修改
C++中使用访问修饰符来实现封装。有三种访问修饰符:private、protected和public13。默认情况下,类中的所有数据成员和成员函数都是私有的,只能在类内部访问1。如果想要提供一个接口给外部访问或修改数据,可以使用公有的成员函数32。
// 封装示例
#include <iostream>
using namespace std;
// 定义一个圆类
class Circle {
private:
// 私有数据成员
double radius;
public:
// 公有构造函数
Circle(double r) {
radius = r;
}
// 公有成员函数
double getArea() {
return 3.14 * radius * radius;
}
};
int main() {
// 创建一个圆对象
Circle c(5);
// 调用公有成员函数获取面积
cout << "Area = " << c.getArea() << endl;
// 尝试直接访问私有数据成员(会报错)
// cout << "Radius = " << c.radius << endl;
return 0;
}
private
C++中的private是一种访问修饰符,它用于限制类成员的可见性和可访问性。private成员只能被该类中的其他成员函数和友元函数访问,不能被该类的对象或外部函数直接访问123。这是C++实现数据封装和隐藏的一种方式14。。
public
所有声明为public的类成员都可以被任何人访问。声明为public的数据成员和成员函数可以被其他类访问123。这是C++实现数据共享和继承的一种方式24。
protected
protected是一种访问修饰符,用来定义类中的受保护成员(数据和函数)。受保护成员只能被以下方式访问:
声明这些成员的类的成员函数
声明这些成员的类的友元
继承自声明这些成员的类的子类的成员函数或友元
// protected示例
#include <iostream>
using namespace std;
// 定义一个基类
class Base
{
protected:
// 受保护数据成员
int x;
public:
// 公有构造函数
Base(int a) {
x = a;
}
};
// 定义一个派生类
class Derived: public Base
{
public:
// 公有构造函数
Derived(int b): Base(b) {}
// 公有成员函数,可以访问基类的受保护数据成员x
void showX() {
cout << "x = " << x << endl;
}
};
int main() {
// 创建一个派生类对象
Derived d(10);
// 调用公有成员函数显示x的值
d.showX();
// 尝试直接访问基类的受保护数据成员x(会报错)
// cout << "x = " << d.x << endl;
return 0;
}
友元函数:
#include <iostream>
using namespace std;
class A
{
private:
int x; // 私有成员
public:
A(int value)
{
x = value; // 构造函数
}
friend void printX(A a); // 声明友元函数
};
// 定义友元函数,可以访问A类的私有成员
void printX(A a)
{
cout << a.x; // 可以访问a.x,因为printX是A类的友元函数
}
int main()
{
A a(10); // 创建A类的对象
printX(a); // 调用友元函数,输出10
return 0;
}
继承
C++的继承体现在类之间。继承是指从一个已有的类(基类)创建一个新的类(派生类)。派生类继承了基类的特征,并且可以有自己的特征1。
单继承
// 继承示例
#include <iostream>
using namespace std;
// 定义一个动物类
class Animal {
protected:
// 受保护数据成员
string name;
public:
// 公有构造函数
Animal(string n) {
name = n;
}
// 公有成员函数,显示动物的名字
void showName() {
cout << "I am " << name << endl;
}
};
// 定义一个狗类,继承自动物类
class Dog: public Animal {
public:
// 公有构造函数,调用基类的构造函数初始化name
Dog(string n): Animal(n) {}
// 公有成员函数,显示狗的叫声
void bark() {
cout << "Woof! Woof!" << endl;
}
};
int main() {
// 创建一个狗对象
Dog d("Jack");
// 调用公有成员函数显示名字和叫声
d.showName();
d.bark();
return 0;
}
多继承
C++支持多重继承,这是指一个类可以从多个基类继承特征和行为。在多重继承中,派生类的构造函数会按照基类的继承顺序依次调用。
// Base class
#include <iostream>
using namespace std;
class Mammal
{
public:
void mammalFunction()
{
cout << "I am a mammal." << endl;
}
};
// Another base class
class WingedAnimal
{
public:
void wingedAnimalFunction()
{
cout << "I have wings." << endl;
}
};
// Derived class
class Bat : public Mammal, public WingedAnimal
{
};
int main()
{
Bat myBat;
myBat.mammalFunction();
myBat.wingedAnimalFunction();
return 0;
}
多态
多态有两种主要的形式:编译时多态和运行时多态。
编译时多态
编译时多态(或静态多态)是指在编译阶段就确定了函数或运算符的具体形式。这种多态是通过函数重载或运算符重载来实现的。例如,我们可以根据参数的个数和类型来定义不同的add()函数。
函数重载:
// function with int parameters
int sum (int a, int b)
{
return a + b;
}
// function with double parameters
double sum (double a, double b)
{
return a + b;
}
int main ()
{
cout << sum (10,20) << '\n'; // calls int version
cout << sum (1.0,1.5) << '\n'; // calls double version
return 0;
}
运算符重载:
#include <iostream>
using namespace std;
class String {
private:
char* s;
int size;
public:
String(const char* s) {
size = strlen(s);
this->s = new char[size + 1];
strcpy(this->s, s);
}
// overload + operator
String operator+(const String& obj) {
int len = size + obj.size;
char* temp = new char[len + 1];
strcpy(temp, s);
strcat(temp, obj.s);
return String(temp);
}
void print() { cout << s << endl; }
};
int main() {
String s1("Hello");
String s2("World");
// concatenate two strings using +
String s3 = s1 + s2;
// print the concatenated string
s3.print();
return 0;
}
运行时多态
运行时多态(或动态多态)是指在运行阶段才确定了函数或运算符的具体形式。这种多态是通过虚函数或抽象类来实现的。例如,我们可以使用基类类型的指针或引用来调用不同子类对象的animalSound()函数。
虚函数:
允许定义一个通用父类,不同的子类继承它并可以实现其虚函数,适合在运行时候动态调用子类时使用,不需要预先确定子类是什么。因此虚函数调用在运行时确定,而不是编译时确定。
#include <iostream>
using namespace std;
class A
{
public:
void foo()
{
cout << "A:foo() is called" << endl;
}
};
class B : public A
{
public:
void foo()
{
cout << "B foo() is called" << endl;
}
};
class C : public A
{
public:
void foo()
{
cout << "C foo() is called" << endl;
}
};
int main()
{
A *a = new B();
A *a = new C();
return 0;
}
抽象类:(C++中的接口)
C++中抽象类是指至少有一个纯虚函数的类12。纯虚函数是指没有定义的函数,只有声明1,。例如,下面的代码展示了一个名为Shape的抽象类,它有一个纯虚函数area():
class Shape {
public:
// pure virtual function
virtual double area() = 0;
};
// 两个从Shape派生出来的具体类Circle和Rectangle,它们都实现了area()函数
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) { radius = r; }
// override pure virtual function
double area() { return 3.14 * radius * radius; }
};
class Rectangle : public Shape {
private:
double length;
double width;
public:
Rectangle(double l, double w) { length = l; width = w; }
// override pure virtual function
double area() { return length * width; }
};
抽象类的目的是提供一个共同的基类,让多个派生类可以共享34。抽象类不能创建对象,只能用指针或引用来操作5。从抽象类派生出来的类必须实现纯虚函数,否则它们也会成为抽象类5。
使用抽象类的好处是可以实现多态性,即用同一种方式处理不同类型的对象23。例如,下面的代码展示了如何用一个Shape指针数组来存储不同类型的形状,并调用它们各自的area()函数:
int main()
{
// Shape s; // error: cannot declare variable 's' to be of abstract type 'Shape'
// create an array of Shape pointers
Shape* shapes[2];
// assign different types of shapes to the array elements
shapes[0] = new Circle(5.0);
shapes[1] = new Rectangle(10.0, 20.0);
// loop through the array and call area() function for each shape
for (int i = 0; i < 2; i++) {
cout << "The area of shape " << i << " is " << shapes[i]->area() << endl;
}
return 0;
}
C#中的接口:
// 定义一个接口,包含一个抽象方法
interface IAnimal
{
void MakeSound();
}
// 定义一个类,实现接口
class Dog : IAnimal
{
// 重写接口方法
public void MakeSound()
{
Console.WriteLine("Woof!");
}
}
// 定义另一个类,实现接口
class Cat : IAnimal
{
// 重写接口方法
public void MakeSound()
{
Console.WriteLine("Meow!");
}
}
// 在主程序中,创建不同的对象,并调用接口方法
class Program
{
static void Main(string[] args)
{
IAnimal dog = new Dog();
dog.MakeSound(); // 输出 Woof!
IAnimal cat = new Cat();
cat.MakeSound(); // 输出 Meow!
}
}
Java中的接口
// 定义一个接口,包含两个抽象方法
interface Language {
public void getType();
public void getVersion();
}
// 定义一个类,实现接口
class Java implements Language {
// 重写接口方法
public void getType() {
System.out.println("Java is an object-oriented language.");
}
public void getVersion() {
System.out.println("The latest version of Java is 17.");
}
}
// 定义另一个类,实现接口
class Python implements Language {
// 重写接口方法
public void getType() {
System.out.println("Python is an interpreted language.");
}
public void getVersion() {
System.out.println("The latest version of Python is 3.10.");
}
}
// 在主程序中,创建不同的对象,并调用接口方法
class Main {
public static void main(String[] args) {
Language java = new Java();
java.getType(); // 输出 Java is an object-oriented language.
java.getVersion(); // 输出 The latest version of Java is 17.
Language python = new Python();
python.getType(); // 输出 Python is an interpreted language.
python.getVersion(); // 输出 The latest version of Python is 3.10.
}
}