宁波网站建设小程序开发,授权登录网站怎么做,网站开发与维护竞赛,装修平台排行榜前十名C中的面向对象到底是什么
对象嘛#xff0c;就和大家都有的对象一样#xff0c;两只眼睛、一个嘴巴、两条腿…… 对不起跑题了#xff0c;C的面向对象中的对象可不是显示中的对象哦#xff0c;但是有一些相似之处#xff0c;有对象的同学可以参考着去学习C面向对象的概念…C中的面向对象到底是什么
对象嘛就和大家都有的对象一样两只眼睛、一个嘴巴、两条腿…… 对不起跑题了C的面向对象中的对象可不是显示中的对象哦但是有一些相似之处有对象的同学可以参考着去学习C面向对象的概念没有对象的同学……那就先new一个出来手动滑稽
面向对象的概念
对象是对某一类事物的抽象表示同时具有属性和方法。属性就是这个对象拥有的一些特征方法就是这个对象可以进行的一些行为。
例如我们大学都必会的“学生管理系统”用C面向对象的思想就是我们把学生看作对象这个对象拥有身高、姓名、学号、班级、成绩等属性同时还有修改班级、设置成绩等方法。
再例如人也是一个对象拥有性别、姓名、户籍地等属性拥有吃饭、睡觉、唱歌等方法。
在C中万物皆可对象也就是我们在开发之前进行系统设计的时候要从面向对象的角度出发先考虑如何通过对象的角度去解决问题规划好各个对象之间的逻辑关系例如老师可以管理学生领导可以管理老师等等。
在C中对象是使用类来实现例如下面的Person类
class Person
{
public:void eat();void sleep();private:int age;string name;string sex;float hight;
}对象和实例
对象是对某一类事物的抽象表示也就是总称实例就是这个对象的一个具体的例子同时也是对象比如人是对象小明就是对象的一个实例但是小明也是人。 例如女朋友是对象拥有身高、体重、性格、饭量等属性还有帮你洗衣服、给你做饭、想你撒娇等方法女朋友A是对象的一个实例女朋友B也是对象的一个实例她们的属性数据不同。
我们平常看到的“对象的实例化”、“实例化一个对象”其实都是一个意思就是由抽象的对象去创建一个个具体的“对象”因为对象实例化产生的实例也是对象。
在C中对象的实例化有下面几种方式
默认构造函数实例化栈上
这是最常见的方式使用类的默认构造函数创建对象。默认构造函数没有参数它会在对象创建时被调用。下面这种方式是在栈上实例化。
class MyClass {
public:MyClass() {// 构造函数的实现}
};int main() {MyClass obj; // 使用默认构造函数实例化对象return 0;
}带参数的构造函数实例化栈上
如果类定义了带参数的构造函数你可以在实例化对象时传递参数给构造函数下面这种方式在栈上实例化
class MyClass {
public:MyClass(int value) {// 构造函数的实现}
};int main() {MyClass obj(42); // 使用带参数的构造函数实例化对象return 0;
}无参数动态内存分配实例化堆上
使用 new 运算符可以在堆上动态地分配内存并调用构造函数来实例化对象需要使用delete手动删除实例化的对象。
class MyClass {
public:MyClass() {// 构造函数的实现}
};int main() {MyClass* obj new MyClass(); // 使用动态内存分配实例化对象// 使用对象delete obj; // 释放内存return 0;
}有参数动态内存分配实例化堆上
使用 new 运算符可以在堆上动态地分配内存并调用构造函数来实例化对象需要使用delete手动删除实例化的对象。
class MyClass {
public:MyClass(int value) {// 构造函数的实现}
};int main() {MyClass* obj new MyClass(10); // 使用动态内存分配实例化对象// 使用对象delete obj; // 释放内存return 0;
}在栈上实例化和在堆上实例化的区别
内存管理
堆上实例化使用 new 运算符在堆上动态分配内存对象的生存期由程序员手动控制。需要显式使用 delete 运算符来释放内存否则可能导致内存泄漏。栈上实例化对象在函数的栈帧上自动分配内存对象的生存期与其所在的作用域相对应。当对象离开作用域时内存会自动被释放无需手动管理。
对象访问
堆上实例化通过指针来访问对象需要使用箭头运算符-来访问对象的成员。栈上实例化通过对象名来直接访问对象的成员。
生命周期
堆上实例化对象可以在程序的任意位置创建和销毁生存期由程序员控制。对象可以在多个作用域中共享。栈上实例化对象的生存期与其所在的作用域相对应当对象离开作用域时自动被销毁。
对象的大小
堆上实例化对象的大小可以是动态的取决于对象的成员和继承关系。对象的大小可能会影响堆的碎片化。栈上实例化对象的大小在编译时确定通常是固定的。
对象初始化
堆上实例化在堆上实例化对象时可以调用带参数的构造函数来初始化对象。栈上实例化在栈上实例化对象时会自动调用构造函数来初始化对象。
面向对象的三大特性
封装
将一些属性和相关方法“集成”在一个对象中对外隐藏内部具体的实现细节外界只需要根据内部提供的接口去使用就可以。
上面的类就体现了封装的概念实例化一个对象之后只需要调用它的方法即可不需要关心内部的实现细节。
继承
我们先明确几个术语
基类父类Base Class被继承的类。派生类子类Derived Class从基类继承得到的类。进一步派生的类孙子类Further Derived Class从派生类再次派生出的类可以视为“孙”类或更远的后代。
继承就是把父类也称为基类的属性和方法继承过来继承也分为三种分别是公有继承public、保护继承protected和私有继承private
通过公有继承基类的公有成员和保护成员在派生类中保持其原有的访问权限公有成员仍为公有保护成员仍为保护而基类的私有成员不能直接被派生类访问但可以通过基类提供的公有或保护方法来访问。通过保护继承基类的公有和保护成员在派生类中都成为保护成员。私有成员仍然保持私有不可直接访问。通过私有继承基类的公有和保护成员在派生类中都成为私有成员。基类的私有成员仍然保持私有不可直接访问。私有继承通常被用于实现细节的隐藏和复用基类的实现而不是其接口。
详细说下保护继承 在保护继承中基类的公有和保护成员在派生类中都成为保护成员意味着这些成员在派生类内部是可访问的但是不能被派生类的对象直接访问。也就是说你不能通过派生类的对象直接访问这些从基类继承来的成员因为它们在派生类中的访问级别是保护的而不是公有的。
当我们继续从这样的派生类再派生出新的类时这些保护成员依然保持保护状态这意味着在这个新的、进一步的派生类中这些成员仍然是可访问的。因为保护成员的特性就是允许在类的内部以及这个类的派生类中访问但不允许通过类的对象进行访问。
假设有三个类Base、Derived从Base通过保护继承得来和FurtherDerived从Derived类继承得来。 Base类有一个公有成员和一个保护成员。
由于是保护继承Derived类中这些成员都成为保护成员Derived类可以访问这些成员但Derived类的对象不能直接访问这些成员。
FurtherDerived类作为Derived的派生类同样可以访问这些从Base继承来的保护成员因为保护成员在整个继承链中都保持保护状态使得它们可以在任何派生类中被访问但不可以被类的对象直接访问。
这种机制允许在类的内部和其派生类之间共享成员同时阻止外部访问从而在一定程度上封装和保护了这些成员。
多态
多多态是面向对象编程中的一个核心概念它指的是不同类的对象对同一消息的响应方式不同或者说同一个接口可以被不同的对象以不同的方式实现。在C中多态主要通过虚函数来实现它允许使用指向基类的指针或引用来调用派生类的方法。
多态主要分为两种类型静态多态和动态多态。
静态多态编译时多态通过函数重载和运算符重载实现。它在编译时决定了使用哪个函数依赖于参数的数量和类型。动态多态运行时多态主要通过虚函数实现。在运行时根据对象的实际类型来调用相应的方法实现了接口的统一和行为的多样。
动态多态的实现依赖于以下几个关键点
虚函数Virtual Function在基类中用virtual关键字声明的函数。派生类可以重写Override这个函数以提供特定的实现。纯虚函数Pure Virtual Function形式为virtual ReturnType FunctionName() 0;。含有纯虚函数的类称为抽象类Abstract Class不能直接实例化。基类指针或引用可以指向派生类的对象并通过这个指针或引用调用虚函数实现动态绑定Dynamic Binding即在运行时决定调用哪个版本的虚函数。
多态内容较多我在后面的博客会详细说名这部分内容。
访问权限修饰符
解释一下几种称呼
派生类继承自父类的子类类外部除了类内部定义和派生类之外的任何地方。在类外部只能访问该类对象的public成员类内部指的是在类的定义内部你可以访问所有public、private和protected成员。
public
公有成员可以在类的内部、派生类以及类的外部访问。使用public修饰的成员在类的接口中非常常见因为它们是类与外界交互的部分。
protected
保护成员可以在类的内部和派生类中访问但不能在类的外部直接访问。保护访问修饰符在基类中定义成员时特别有用这些成员需要对派生类可见但对其他外部类或函数不可见。
protected成员不能被类的对象访问因为类的对象属于类外部
private
私有成员只能在类的内部访问。即使是该类的派生类也无法访问私有成员。私有访问限制是类封装的一个重要方面它防止了外部对类内部实现细节的直接访问。
访问权限总结
访问修饰符类内部类外部派生类public可访问可访问可访问protected可访问不可访问可访问private可访问不可访问不可访问
为什么要面向对象编程
面向对象编程真的是为开发者带来了极大的便利。 封装我们通过将一类事物封装成一个对象隐藏内部的实现细节我们只需要为这个对象设计一组接口开发者可以直接调用此接口去进行其他操作而不必思考这个接口内部的实现细节。这种信息隐藏的特性有助于降低系统复杂性提高模块的独立性从而使得软件易于理解、修改和扩展。
继承允许新创建的类派生类继承现有类基类的属性和方法。这促进了代码的重用允许新的类重写或扩展基类的功能。通过继承可以创建出具有层次结构的类体系有助于组织和管理复杂的代码。
多态可以使得一个接口可以用不同的方式来实现增加了代码的灵活性和可扩展性。这也是实现插件架构和依赖注入等设计模式的关键。
此外封装、继承和多态也支持了代码的低耦合性这使得修改和维护现有代码更加容易。
另外类的抽象性允许开发者专注于高层次的操作而不是底层的实现细节。通过定义具有通用功能的类可以创建抽象的表示这减少了代码的复杂性并提高了代码的可理解性。并且面向对象的概念支持软件工程的基本原则如模块性、封装性和复用性。这些原则是构建大型系统和复杂应用程序的基石有助于降低软件开发和维护的复杂性。