本文介绍了C++面向对象的基础概念,包括类和对象的基本理解、成员变量与成员函数、构造函数与析构函数。文章还详细讲解了封装、继承和多态性等重要特性,并提供了多个示例代码来帮助理解。此外,文中还探讨了面向对象编程的设计原则及其应用,为读者提供了全面的C++面向对象编程知识。
C++面向对象基础概念
面向对象编程是现代软件开发的重要基石之一,C++作为一门强大的编程语言,全面支持面向对象的编程范式。本文将介绍C++中面向对象的基础概念,包括类和对象的基本理解、成员变量与成员函数、以及构造函数与析构函数。
类和对象的基本理解
在C++中,类(Class)是对象的蓝图,它定义了一组相关的变量(成员变量)和函数(成员函数),这些变量和函数共同描述了对象的状态和行为。对象(Object)则是类的一个具体实例,它包含了类定义的数据成员和成员函数的具体值。
// 定义一个简单的类
class Car {
public:
// 成员变量
int year;
std::string make;
std::string model;
// 成员函数
void displayInfo() {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
// 创建一个Car对象
Car myCar;
myCar.year = 2020;
myCar.make = "Toyota";
myCar.model = "Camry";
// 调用成员函数
myCar.displayInfo();
return 0;
}
成员变量与成员函数
成员变量(Member Variables)是类中定义的数据成员,用来存储对象的状态。成员函数(Member Functions)是类定义中的函数,用来描述对象的行为或者状态变化。
class Car {
public:
int year;
std::string make;
std::string model;
void setYear(int y) {
year = y;
}
void setMake(std::string m) {
make = m;
}
void setModel(std::string mod) {
model = mod;
}
void displayInfo() {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Car myCar;
myCar.setMake("Toyota");
myCar.setModel("Camry");
myCar.setYear(2020);
myCar.displayInfo();
return 0;
}
构造函数与析构函数
构造函数(Constructor)是一种特殊的成员函数,用于初始化新创建的对象。它在对象创建时自动调用,名称与类名相同,没有返回类型。
析构函数(Destructor)是一种特殊的成员函数,用于清理和释放对象使用的资源。它在对象被销毁之前自动调用,名称前加一个波浪线(~
)。
class Car {
public:
int year;
std::string make;
std::string model;
// 构造函数
Car(int y, std::string m, std::string mod) {
year = y;
make = m;
model = mod;
}
// 析构函数
~Car() {
std::cout << "Car object is being destroyed." << std::endl;
}
void displayInfo() {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
{
Car myCar(2020, "Toyota", "Camry");
myCar.displayInfo();
} // 析构函数在这里被自动调用
return 0;
}
封装
封装是面向对象编程中一个重要的概念,它通过将对象的内部实现细节隐藏起来,只暴露必要的接口,从而增加程序的安全性和可维护性。C++中,封装是通过访问权限来实现的。
私有、保护、公有访问权限
在C++中,成员变量和成员函数可以通过访问权限来声明。这些访问权限包括私有(Private)、保护(Protected)和公共(Public)。
- 私有(Private):只能在类的内部访问,不可从类的外部访问。
- 保护(Protected):只能在类及其派生类内部访问。
- 公有(Public):可以被任何访问到该类的对象所访问。
class Car {
private:
int year;
std::string make;
std::string model;
public:
Car(int y, std::string m, std::string mod) : year(y), make(m), model(mod) {}
void setYear(int y) {
year = y;
}
void setMake(std::string m) {
make = m;
}
void setModel(std::string mod) {
model = mod;
}
void displayInfo() {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Car myCar(2020, "Toyota", "Camry");
myCar.displayInfo();
// 尝试修改私有变量
myCar.year = 2010; // 编译错误,year为私有成员变量
myCar.setYear(2010); // 正确,通过公有成员函数修改私有变量
myCar.displayInfo();
return 0;
}
作用域解析运算符
作用域解析运算符(::
)主要用于访问类中的成员变量和成员函数。它可以在不同的作用域中解析成员,比如在类的内部和外部。
class Car {
private:
int year;
std::string make;
std::string model;
public:
Car(int y, std::string m, std::string mod) : year(y), make(m), model(mod) {}
void setYear(int y) {
::year = y;
}
void setMake(std::string m) {
::make = m;
}
void setModel(std::string mod) {
::model = mod;
}
void displayInfo() {
::std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Car myCar(2020, "Toyota", "Camry");
myCar.displayInfo();
// 使用作用域解析运算符访问成员变量和成员函数
::Car::setYear(myCar, 2010);
myCar.displayInfo();
return 0;
}
继承
继承是面向对象编程中的另一个核心概念,它允许一个类(子类或派生类)继承另一个类(基类或父类)的属性和行为。这样可以实现代码的重用和扩展。
单继承和多继承
单继承是指一个子类只能有一个直接基类,而多继承是指一个子类可以有多个直接基类。
class Vehicle {
public:
int year;
std::string make;
std::string model;
Vehicle(int y, std::string m, std::string mod) : year(y), make(m), model(mod) {}
void displayInfo() {
std::cout << "Vehicle: " << make << " " << model << ", Year: " << year << std::endl;
}
};
class Car : public Vehicle {
public:
Car(int y, std::string m, std::string mod) : Vehicle(y, m, mod) {}
void displayInfo() {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Car myCar(2020, "Toyota", "Camry");
myCar.displayInfo();
return 0;
}
多继承示例:
class Engine {
public:
int horsepower;
Engine(int hp) : horsepower(hp) {}
void displayInfo() {
std::cout << "Engine: " << horsepower << " horsepower" << std::endl;
}
};
class Car : public Vehicle, public Engine {
public:
Car(int y, std::string m, std::string mod, int hp) : Vehicle(y, m, mod), Engine(hp) {}
void displayInfo() {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
std::cout << "Engine: " << horsepower << " horsepower" << std::endl;
}
};
int main() {
Car myCar(2020, "Toyota", "Camry", 200);
myCar.displayInfo();
return 0;
}
虚函数与纯虚函数
虚函数(Virtual Function)是一种允许动态绑定的成员函数。在基类中声明虚函数,派生类可以覆盖这些虚函数,以提供更具体的实现。纯虚函数(Pure Virtual Function)是一种特殊的虚函数,它没有具体的实现,但要求派生类必须实现这些函数。
class Vehicle {
public:
int year;
std::string make;
std::string model;
Vehicle(int y, std::string m, std::string mod) : year(y), make(m), model(mod) {}
virtual void displayInfo() {
std::cout << "Vehicle: " << make << " " << model << ", Year: " << year << std::endl;
}
};
class Car : public Vehicle {
public:
Car(int y, std::string m, std::string mod) : Vehicle(y, m, mod) {}
void displayInfo() override {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Vehicle *myVehicle = new Car(2020, "Toyota", "Camry");
myVehicle->displayInfo();
return 0;
}
纯虚函数示例:
class Engine {
public:
int horsepower;
Engine(int hp) : horsepower(hp) {}
virtual void displayInfo() = 0; // 纯虚函数
};
class GasEngine : public Engine {
public:
GasEngine(int hp) : Engine(hp) {}
void displayInfo() override {
std::cout << "Gas Engine: " << horsepower << " horsepower" << std::endl;
}
};
class ElectricEngine : public Engine {
public:
ElectricEngine(int hp) : Engine(hp) {}
void displayInfo() override {
std::cout << "Electric Engine: " << horsepower << " horsepower" << std::endl;
}
};
int main() {
Engine *engine1 = new GasEngine(200);
engine1->displayInfo();
Engine *engine2 = new ElectricEngine(300);
engine2->displayInfo();
return 0;
}
多态性
多态性(Polymorphism)是面向对象编程中的一个关键特性,它允许通过基类指针或引用调用派生类的成员函数。多态性分为动态绑定和静态绑定。
动态与静态绑定
静态绑定(Static Binding)在编译时确定调用哪个函数,而动态绑定(Dynamic Binding)在运行时确定调用哪个函数。
动态绑定示例:
class Vehicle {
public:
int year;
std::string make;
std::string model;
Vehicle(int y, std::string m, std::string mod) : year(y), make(m), model(mod) {}
virtual void displayInfo() {
std::cout << "Vehicle: " << make << " " << model << ", Year: " << year << std::endl;
}
};
class Car : public Vehicle {
public:
Car(int y, std::string m, std::string mod) : Vehicle(y, m, mod) {}
void displayInfo() override {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Vehicle *myVehicle = new Car(2020, "Toyota", "Camry");
myVehicle->displayInfo();
return 0;
}
静态绑定示例(编译时绑定):
class Vehicle {
public:
int year;
std::string make;
std::string model;
Vehicle(int y, std::string m, std::string mod) : year(y), make(m), model(mod) {}
void displayInfo() {
std::cout << "Vehicle: " << make << " " << model << ", Year: " << year << std::endl;
}
};
class Car : public Vehicle {
public:
Car(int y, std::string m, std::string mod) : Vehicle(y, m, mod) {}
void displayInfo() {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Car myCar(2020, "Toyota", "Camry");
myCar.displayInfo();
return 0;
}
虚函数的使用
虚函数允许通过基类指针或引用调用派生类的成员函数,从而实现动态绑定。
class Vehicle {
public:
int year;
std::string make;
std::string model;
Vehicle(int y, std::string m, std::string mod) : year(y), make(m), model(mod) {}
virtual void displayInfo() {
std::cout << "Vehicle: " << make << " " << model << ", Year: " << year << std::endl;
}
};
class Car : public Vehicle {
public:
Car(int y, std::string m, std::string mod) : Vehicle(y, m, mod) {}
void displayInfo() override {
std::cout << "Car: " << make << " " << model << ", Year: " << year << std::endl;
}
};
int main() {
Vehicle *myVehicle = new Car(2020, "Toyota", "Camry");
myVehicle->displayInfo();
return 0;
}
虚拟与接口类
虚拟基类(Virtual Base Class)可以解决多继承中的重复继承问题,而接口类(Interface Class)是一种特殊的类,它定义了一组纯虚函数,提供了一组规范化的接口。
抽象类与接口类的应用
抽象类(Abstract Class)是一种不能直接实例化的类,它通常包含一个或多个纯虚函数。接口类是一种特殊的抽象类,它仅包含纯虚函数,没有数据成员。
class Engine {
public:
virtual void displayInfo() = 0;
};
class GasEngine : public Engine {
public:
int horsepower;
GasEngine(int hp) : horsepower(hp) {}
void displayInfo() override {
std::cout << "Gas Engine: " << horsepower << " horsepower" << std::endl;
}
};
class ElectricEngine : public Engine {
public:
int horsepower;
ElectricEngine(int hp) : horsepower(hp) {}
void displayInfo() override {
std::cout << "Electric Engine: " << horsepower << " horsepower" << std::endl;
}
};
int main() {
Engine *engine1 = new GasEngine(200);
engine1->displayInfo();
Engine *engine2 = new ElectricEngine(300);
engine2->displayInfo();
return 0;
}
虚拟基类示例:
class Base {
public:
virtual void displayInfo() = 0;
};
class Derived1 : virtual public Base {
public:
void displayInfo() override {
std::cout << "Derived1" << std::endl;
}
};
class Derived2 : virtual public Base {
public:
void displayInfo() override {
std::cout << "Derived2" << std::endl;
}
};
class Derived3 : public Derived1, public Derived2 {
public:
void displayInfo() override {
Derived1::displayInfo();
Derived2::displayInfo();
}
};
int main() {
Derived3 obj;
obj.displayInfo();
return 0;
}
面向对象编程设计原则
面向对象编程的设计原则是确保软件的可维护性和可扩展性,这些原则包括单一职责原则、开闭原则、里氏替换原则、接口隔离原则、依赖倒置原则和责任链原则。
单一职责原则(SRP)
单一职责原则是指一个类应该只有一个引起它变化的原因。这意味着一个类应该只有一个功能,避免多个职责混合在一起。
class Car {
public:
void drive() {
std::cout << "Driving the car." << std::endl;
}
void park() {
std::cout << "Parking the car." << std::endl;
}
};
class ParkingSystem {
public:
void parkCar(Car car) {
std::cout << "Parking car in the system." << std::endl;
}
};
int main() {
Car myCar;
myCar.drive();
myCar.park();
ParkingSystem parkingSystem;
parkingSystem.parkCar(myCar);
return 0;
}
开闭原则(OCP)
开闭原则是指软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在不修改现有代码的情况下,应该能够扩展类的功能。
class Vehicle {
public:
virtual void drive() = 0;
};
class Car : public Vehicle {
public:
void drive() override {
std::cout << "Driving the car." << std::endl;
}
};
class Motorcycle : public Vehicle {
public:
void drive() override {
std::cout << "Driving the motorcycle." << std::endl;
}
};
int main() {
Vehicle *car = new Car();
car->drive();
Vehicle *motorcycle = new Motorcycle();
motorcycle->drive();
return 0;
}
里氏替换原则(LSP)
里氏替换原则是指子类对象应该能够替换基类对象,而不影响程序的正确性。这意味着派生类对象可以在任何基类对象出现的地方使用。
class Shape {
public:
virtual double area() = 0;
};
class Rectangle : public Shape {
public:
int width;
int height;
Rectangle(int w, int h) : width(w), height(h) {}
double area() override {
return width * height;
}
};
class Circle : public Shape {
public:
int radius;
Circle(int r) : radius(r) {}
double area() override {
return 3.14 * radius * radius;
}
};
int main() {
std::vector<Shape*> shapes;
shapes.push_back(new Rectangle(4, 5));
shapes.push_back(new Circle(3));
for (Shape* shape : shapes) {
std::cout << "Area: " << shape->area() << std::endl;
}
return 0;
}
接口隔离原则(ISP)
接口隔离原则是指不应该强迫客户端依赖它们不需要的接口。这意味着应该将接口分解成更小的、更具体的接口,以满足特定客户端的需求。
class Keyboard {
public:
void typeText() {
std::cout << "Typing text." << std::endl;
}
};
class Mouse {
public:
void click() {
std::cout << "Clicking the mouse." << std::endl;
}
};
class Computer {
public:
Keyboard keyboard;
Mouse mouse;
void useKeyboard() {
keyboard.typeText();
}
void useMouse() {
mouse.click();
}
};
int main() {
Computer computer;
computer.useKeyboard();
computer.useMouse();
return 0;
}
依赖倒置原则(DIP)
依赖倒置原则是指抽象不应该依赖于细节,细节应该依赖于抽象。这意味着应该通过接口或抽象类而不是具体类来实现依赖关系。
class Engine {
public:
virtual void start() = 0;
virtual void stop() = 0;
};
class GasEngine : public Engine {
public:
void start() override {
std::cout << "Starting gas engine." << std::endl;
}
void stop() override {
std::cout << "Stopping gas engine." << std::endl;
}
};
class ElectricEngine : public Engine {
public:
void start() override {
std::cout << "Starting electric engine." << std::endl;
}
void stop() override {
std::cout << "Stopping electric engine." << std::endl;
}
};
class Car {
private:
Engine* engine;
public:
Car(Engine* e) : engine(e) {}
void startEngine() {
engine->start();
}
void stopEngine() {
engine->stop();
}
};
int main() {
Engine* gasEngine = new GasEngine();
Car gasCar(gasEngine);
gasCar.startEngine();
gasCar.stopEngine();
Engine* electricEngine = new ElectricEngine();
Car electricCar(electricEngine);
electricCar.startEngine();
electricCar.stopEngine();
return 0;
}
责任链原则(Chain of Responsibility)
责任链原则是指请求可以在责任链上传递,直到有一个对象处理它为止。这意味着请求可以通过多个处理者传递,直到找到一个合适的处理者来处理它。
class Handler {
public:
virtual void handleRequest() = 0;
};
class ConcreteHandler1 : public Handler {
public:
void handleRequest() override {
std::cout << "ConcreteHandler1 handling request." << std::endl;
}
};
class ConcreteHandler2 : public Handler {
public:
void handleRequest() override {
std::cout << "ConcreteHandler2 handling request." << std::endl;
}
};
class Client {
private:
Handler* handler1;
Handler* handler2;
public:
Client(Handler* h1, Handler* h2) : handler1(h1), handler2(h2) {}
void setNextHandler(Handler* nextHandler) {
handler2 = nextHandler;
}
void request() {
handler1->handleRequest();
handler2->handleRequest();
}
};
int main() {
ConcreteHandler1 handler1;
ConcreteHandler2 handler2;
Client client(&handler1, &handler2);
client.request();
client.setNextHandler(&handler2);
client.request();
return 0;
}
通过以上示例和代码演示,我们可以看到C++语言中面向对象编程的各个重要概念和设计原则。这些概念不仅增强了代码的组织和复用,还使得代码更加灵活和易于扩展。通过遵循这些原则,可以编写出更加健壮和可维护的程序。
共同学习,写下你的评论
评论加载中...
作者其他优质文章