这里写目录标题

封装C语言封装风格C++封装

继承多态多态的实现虚函数概念:虚表指针overloadoverwriteoverride抽象类

重载

封装

C++中的封装是一种面向对象编程的概念,它将数据(成员变量)和操作(成员函数)封装在一个类中,通过访问控制来限制对类内部实现的访问。封装提供了类与外部世界之间的接口,隐藏了类的内部实现细节,提高了代码的可维护性和安全性。

在C++中,封装可以通过使用访问修饰符(public、private、protected)来实现:

public(公有)访问修饰符允许类的成员在类的外部被访问,也可以在类的内部被访问。通常将公有成员函数作为类的接口,供外部使用。 private(私有)访问修饰符将类的成员隐藏在类的内部,外部无法直接访问私有成员变量和私有成员函数。通常将私有成员用于实现类的内部逻辑。 protected(保护)访问修饰符与私有访问修饰符类似,但允许派生类(子类)访问基类中的保护成员。 下面是一个简单的封装示例:

class MyClass {

private:

int privateData; // 私有成员变量

public:

void setPrivateData(int data) { // 公有成员函数

privateData = data;

}

int getPrivateData() const { // 公有成员函数

return privateData;

}

};

int main() {

MyClass obj;

obj.setPrivateData(42);

int data = obj.getPrivateData();

return 0;

}

在上面的示例中,私有成员变量privateData被封装在类MyClass中,外部无法直接访问。通过公有成员函数setPrivateData和getPrivateData来操作私有成员变量。

封装可以提供更好的代码组织和管理方式,同时也增强了代码的安全性,因为外部代码无法直接修改和访问类的内部数据。

C语言封装风格

当单一变量无法完成描述需求的时候,结构体类型解决了这问题。可以将多个类型打包成一体,形成新的类型,这是c语言中封装的概念。但是,新类型并不包含对数据类的操作,所有操作都是通过函数的方式,去进行封装。

1 #include

2 #include

3 using namespace std;

4

5 struct person

6 {

7 string name;

8 int age;

9 int height;

10 };

11 void init(person* p)

12 {

13 p->name = "jiejie";

14 p->age = 20;

15 p->height = 130;

16 }

17 void show(person p)

18 {

19 cout<<"p.name = "<

20 cout<<"p.age = "<

21 cout<<"p.height = "<

22 }

23 int main()

24 {

25 person per;

26 init(&per);

27 show(per);

28

29 return 0;

30 }

把数据放到一起用struct包装,然后把数据以引用或指针的方式传给行为。

C++封装

C++的封装认为C语言的封装不彻底,对于数据和行为分类,没有权限控制。 C++则提供控制选择,将数据和行为放在一起,对内开放数据,逻辑抽象。对外提供接口

1 #include

2 using namespace std;

3

4 class person

5 {

6 public:

7 int num;

8 void init()

9 {

10 cin>>this->num;

11 cin>>this->age;

12 cin>>this->height;

13 }

14 void show()

15 {

16 cout<

17 cout<

18 cout<

19 }

20

21 protected:

22 int age;

23 private:

24 int height;

25 };

26 int main()

27 {

28 person p;

29 p.init();

30 p.show();

31 return 0;

32 }

基本流程: 通过创建一个类,再通过创建类对象 再由对象调用行为,完成需求。

继承

C++中的继承是面向对象编程的一个重要概念,它允许一个类(派生类/子类)从另一个类(基类/父类)继承属性和行为。继承可以通过创建一个新类并从基类派生来实现,新类将自动获得基类的成员变量和成员函数,同时可以添加新的成员或重写基类的成员函数。

继承的主要目的是实现代码的重用和构建类之间的层次关系。在继承关系中,基类被称为超类或父类,派生类被称为子类。 一般定义格式如下:

class 派生类名标识符: [继承方式] 基类名标识符

{

[访问控制修饰符]

[成员声明列表]

};

继承方式有3种,分别为公有型,保护型和私有型,访问控制修饰符也是public,protected,private 类型。 成员声明列表中包含类成员变量以及成员函数,是派生类新增的成员。 “:”是一个运算符,表示基类和派生类之间的继承关系。

C++中的继承有以下几种类型:

公有继承(public inheritance):派生类继承了基类的公有成员和保护成员,并且这些成员在派生类中的访问权限与基类中的一样。派生类的对象可以直接访问基类的公有成员。

私有继承(private inheritance):派生类继承了基类的公有成员和保护成员,但是这些成员在派生类中的访问权限变为私有。派生类的对象不能直接访问基类的公有成员,只能通过派生类的成员函数来间接访问。

保护继承(protected inheritance):派生类继承了基类的公有成员和保护成员,但是这些成员在派生类中的访问权限变为保护。派生类的对象不能直接访问基类的公有成员,只能通过派生类的成员函数来间接访问。

在C++中,使用关键字class或struct来定义一个类,并使用关键字public、private或protected来指定成员的访问权限。

下面是一个简单的继承示例:

class Shape {

public:

void draw() {

std::cout << "Drawing a shape" << std::endl;

}

};

class Rectangle : public Shape {

public:

void draw() {

std::cout << "Drawing a rectangle" << std::endl;

}

};

int main() {

Shape shape;

shape.draw(); // 输出:"Drawing a shape"

Rectangle rectangle;

rectangle.draw(); // 输出:"Drawing a rectangle"

return 0;

}

在上面的示例中,Shape类是基类,它有一个公有成员函数draw。Rectangle类是派生类,通过public关键字继承了Shape类。Rectangle类重写了draw函数,实现了自己的绘制行为。在main函数中,我们分别创建了Shape对象和Rectangle对象,并调用了它们的draw函数。

继承是一种强大的代码复用工具,它可以使得类之间的关系更加清晰和有组织。通过继承,派生类可以继承基类的接口和实现,并且可以添加自己的功能或修改基类的行为。

继承是面对对象的主要特性之一,它使一个类可以从现有类中派生,而不必重新定义一个类。

实质:用已有的数据类型创建新的数据类型,并保留已有数据类型的特点,以旧类为基础创建新类,新类包含旧类的数据成员和成员函数。并且·可以在新类中添加新的数据成员和成员函数。 旧类被称为基类或者父类,新类被称为派生类或者子类。

多态

C++中的多态是面向对象编程的一个重要概念,它允许使用指针或引用来处理不同类型的对象,而实际上执行的是根据对象类型动态选择的相关操作。多态性可以提高代码的灵活性、可复用性和可扩展性。

C++中的多态性主要通过虚函数(virtual function)和运行时类型识别(runtime type identification)两个机制来实现:

虚函数:在基类中声明虚函数,并在派生类中进行重写。当通过指向基类的指针或引用调用虚函数时,将根据实际对象的类型来选择正确的函数实现。这种动态选择函数的机制称为动态绑定(dynamic binding)。虚函数通过关键字virtual进行声明。

运行时类型识别(RTTI):C++提供了dynamic_cast和typeid两个运算符来进行运行时类型识别。dynamic_cast用于将基类指针或引用转换为派生类指针或引用,如果转换成功,返回指向派生类的指针或引用;如果转换失败,则返回空指针或抛出bad_cast异常。typeid用于获取表达式的实际类型。

下面是一个简单的多态示例:

#include

class Shape {

public:

virtual void draw() {

std::cout << "Drawing a shape" << std::endl;

}

};

class Rectangle : public Shape {

public:

void draw() override {

std::cout << "Drawing a rectangle" << std::endl;

}

};

class Circle : public Shape {

public:

void draw() override {

std::cout << "Drawing a circle" << std::endl;

}

};

int main() {

Shape* shapePtr;

Rectangle rectangle;

Circle circle;

shapePtr = &rectangle;

shapePtr->draw(); // 输出:"Drawing a rectangle"

shapePtr = &circle;

shapePtr->draw(); // 输出:"Drawing a circle"

return 0;

}

在上面的示例中,Shape类有一个虚函数draw,Rectangle和Circle类分别是派生自Shape的两个子类,并重写了draw函数。在main函数中,我们使用指向基类的指针shapePtr来处理不同类型的对象。通过将shapePtr指向Rectangle对象和Circle对象,并调用draw函数,会根据对象的实际类型选择正确的函数实现。

多态性使得我们可以以一种统一的方式来处理不同类型的对象,而不需要关心对象的具体类型。这样可以使代码更具灵活性和可维护性,同时提供了一种机制来实现运行时的动态行为。

多态的实现

静态绑定:在编译期决定 函数重载 运算符重载 模板 动态绑定:在程序运行时执行 虚函数

虚函数概念:

在基类中冠以关键字virtual的成员函数 定义: virtual函数类型 函数名称(参数列表) 如果一个函数在基类中被声明为虚函数,则它在所有派生类中都是虚函数。 只有通过基类指针或引用调用虚函数才能引发动态绑定 虚函数不能声明为静态 如果一个类要做为多态基类,要将析构函数定义为虚函数

虚表指针

虚函数的动态绑定是通过虚表来实现的 包含虚函数的类头4个字节存放指向虚表的指针

overload

成员函数被重载的特征: 相同的范围(在同一类中) 函数名字相同 参数不同 virtual关键字可有可无

overwrite

覆盖是指派生类函数覆盖基类函数 特征是: 不同的范围 函数名字相同 参数相同 基类函数必须有virtual关键字

override

重定义(派生类与基类) 不同的范围(分贝位于派生类和基类) 函数名与参数都相同,无virtual关键字 函数名相同,参数不同,virtual可有可无

抽象类

作用: 抽象类作为抽象设计的目的而声明,将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。 对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现 注意: 抽象类只能作为基类来使用 不能声明抽象类的对象,可以使用抽象类的指针和引用 构造函数不能是虚函数,析构函数可以是虚函数 可以试用指向抽象类的指针支持运行时多态性 派生类中必须实现基类中的纯虚函数,否则被看做一个抽象类

对于一个没有任何接口的类,如果想要将它定义成抽象类,只能将虚构函数声明为纯虚的 通常情况下在基类中纯虚函数不需要实现,例外是纯析构函数要给出实现

重载

在C++中,函数重载(Function Overloading)是指在同一个作用域内,可以定义多个具有相同名称但参数列表不同的函数。通过函数重载,可以根据参数的类型、顺序和个数来区分不同的函数,并且可以为相同的操作提供不同的实现。

函数重载的特点如下:

函数名称相同:重载的函数必须具有相同的名称。

参数列表不同:重载的函数必须具有不同的参数列表,可以通过参数的类型、顺序和个数的不同来区分。

返回值类型不同不足以实现函数重载:函数的返回值类型不能作为重载函数的区分标准,因为函数调用时通常会忽略返回值。

举例如下所示:

#include

using namespace std;

class interage

{

int inter;

public:

interage(int in)

{

inter = in;

};

~interage(){};

interage& operator++()

{

++inter;

return *this;

}

interage operator++(int in)

{

interage temp(inter);

inter++;

return temp;

}

void display()

{

cout<

}

};

int main()

{

interage in(10);

in.display();

interage in2 = ++(++in);

in2.display();

interage in3 = in2++;

in3.display();

in3.display();

return 0;

}

通过函数重载,我们可以在C++中实现更加灵活和易于使用的代码。函数重载允许我们使用相同的函数名,但根据参数的类型、顺序和个数来区分不同的函数。这样,我们可以提供不同的函数实现来处理各种情况,而无需为每种情况编写不同的函数名称。

函数重载使得代码更具可读性和可维护性,同时提供了一种方便的方式来进行函数扩展和适应不同的需求。然而,在使用函数重载时,需要注意避免产生歧义或混淆,确保函数之间的区分明确。

总而言之,函数重载是C++中一个强大的特性,可以使代码更加灵活和易于使用,为我们提供了更多的选择和可能性。合理地利用函数重载,可以使我们的代码更加清晰、高效,同时提高开发效率和代码的可维护性。

好文阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。