招商网站建设的必要性,做调查可以赚钱的网站,深圳百度关键词,网站建设7个基本流程C面向对象编程入门与进阶1. 面向对象基础概念在C面向对象编程中#xff0c;对象创建时必须调用构造函数。若不调用默认构造函数#xff0c;创建对象时就需向构造函数传递参数。方法可以像独立函数一样重载#xff0c;一个类只要参数列表不同#xff0c;就可以有多个构造函数…C面向对象编程入门与进阶1. 面向对象基础概念在C面向对象编程中对象创建时必须调用构造函数。若不调用默认构造函数创建对象时就需向构造函数传递参数。方法可以像独立函数一样重载一个类只要参数列表不同就可以有多个构造函数。不过类只能有一个析构函数因为它不能有参数所以无法重载。修饰器用于修改类的字段检查器则用于查看这些字段。2. 第一个示例汽车类我们以汽车为例汽车可以加速、减速、左转、右转还能读取速度和方向。2.1 类的定义代码通常分为多个文件一个头文件通常以.h为扩展名包含类的定义、一个实现文件以.cpp为扩展名包含方法的定义主函数常放在第三个文件中。这里的文件分别为Car.h、Car.cpp和Main.cpp。// Car.h class Car { public: Car(); Car(int iSpeed, int iDirection); ~Car(); void IncreaseSpeed(int iSpeed); void DecreaseSpeed(int iSpeed); void TurnLeft(int iAngle); void TurnRight(int iAngle); int GetSpeed(); int GetDirection(); private: int m_iSpeed, m_iDirection; };2.2 方法的实现在每个类的实现文件中都要包含头文件。每个方法都要用类名加两个冒号如Car::标记以区分类方法和独立函数。// Car.cpp #include Car.h Car::Car() :m_iSpeed(0), m_iDirection(0) { // Empty. } Car::Car(int iSpeed, int iDirection) :m_iSpeed(iSpeed), m_iDirection(iDirection) { // Empty. } Car::~Car() { // Empty. } void Car::IncreaseSpeed(int iSpeed) { m_iSpeed iSpeed; } void Car::DecreaseSpeed(int iSpeed) { m_iSpeed - iSpeed; } void Car::TurnLeft(int iAngle) { m_iDirection - iAngle; } void Car::TurnRight(int iAngle) { m_iDirection iAngle; } int Car::GetSpeed() { return m_iSpeed; } int Car::GetDirection() { return m_iDirection; }2.3 主函数的使用主函数文件也需包含头文件。创建对象时写下类名和对象名。若类中有构造函数需传递匹配的实际参数列表默认构造函数则无需参数。// Main.cpp #include iostream using namespace std; #include Car.h void main() { Car car1(100, 90); cout Car1: car1.GetSpeed() // 100 degrees, car1.GetDirection() // 90 miles per hour endl; Car car2(150, 0); car2.TurnRight(180); cout Car2: car2.GetSpeed() // 150 degrees, car2.GetDirection() // 180 miles per hour endl; Car car3; car3.IncreaseSpeed(200); car3.TurnRight(270); cout Car3: car3.GetSpeed() // 200 degrees, car3.GetDirection() // 270 miles per hour endl; // Causes a compiler error as m_iSpeed is a private member. // cout Speed: car3.m_iSpeed endl; }3. 第二个示例银行账户类这次我们模拟一个银行账户有一些新的特性。3.1 常量字段和常量方法可以在类中定义常量字段它只能由构造函数初始化之后不能修改如这里的账户号码。只有检查器可以定义为常量方法因为常量方法不能修改字段的值。3.2 复制构造函数类中添加了复制构造函数用于创建对象的副本。新对象可以用括号或赋值运算符初始化。// BankAccount.h class BankAccount { public: BankAccount(int iNumber, double dSaldo 0); BankAccount(const BankAccount bankAccount); void Deposit(double dAmount) {m_dSaldo dAmount;} void Withdraw(double dAmount) {m_dSaldo - dAmount;} int GetNumber() const {return m_iNUMBER;} double GetSaldo() const {return m_dSaldo; } private: const int m_iNUMBER; double m_dSaldo; };// BankAccount.cpp #include BankAccount.h BankAccount::BankAccount(int iNumber, double dSaldo /* 0 */) :m_iNUMBER(iNumber), m_dSaldo(dSaldo) { // Empty. } BankAccount::BankAccount(const BankAccount bankAccount) :m_iNUMBER(bankAccount.m_iNUMBER), m_dSaldo(bankAccount.m_dSaldo) { // Empty. }// Main.cpp #include iostream using namespace std; #include BankAccount.h void main() { BankAccount account1(123); account1.Deposit(100); cout Account1: number account1.GetNumber() // 123 , $ account1.GetSaldo() endl; // 100 account1.Withdraw(50); cout Account1: number account1.GetNumber() // 123 , $ account1.GetSaldo() endl; // 50 BankAccount copyAccount(account1); cout Copy Account: number copyAccount.GetNumber() , $ copyAccount.GetSaldo() endl; // 50, 123 const BankAccount account2(124, 200); cout Account2: number account2.GetNumber() // 124 , $ account2.GetSaldo() endl; // 200 // Would cause a compiler error. // account2.Withdraw(50); }4. 继承与动态绑定4.1 类的继承将三个类组合成一个类层次结构以Person类为基类Student和Employee为子类。子类继承基类的所有公共成员通常也继承受保护成员。// Person.h class Person { public: Person(string stName); virtual void Print() const; private: string m_stName; };// Person.cpp #include iostream #include string using namespace std; #include Person.h Person::Person(string stName) :m_stName(stName) { // Empty. } void Person::Print() const { cout Name: m_stName endl; }// Student.h class Student : public Person { public: Student(string stName, string stUniversity); void Print() const; private: string m_stUniversity; };// Student.cpp #include iostream #include string using namespace std; #include Person.h #include Student.h Student::Student(string stName, string stUniversity) :Person(stName), m_stUniversity(stUniversity) { // Empty. } void Student::Print() const { Person::Print(); cout University: m_stUniversity endl; }// Employee.h class Employee : public Person { public: Employee(string stName, string stEmployer); void Print() const; private: string m_stEmployer; };// Employee.cpp #include iostream #include string using namespace std; #include Person.h #include Employee.h Employee::Employee(string stName, string stEmployer) :Person(stName), m_stEmployer(stEmployer) { // Empty. } void Employee::Print() const { Person::Print(); cout Company: m_stEmployer endl; }4.2 动态绑定当Person类的Print方法标记为virtual时使用指向基类对象的指针指向子类对象会根据实际指向的对象调用相应的Print方法。// Main.cpp #include iostream using namespace std; #include Person.h #include Student.h #include Employee.h void main() { Person person(John Smith); person.Print(); cout endl; Student student(Mark Jones, MIT); student.Print(); cout endl; Employee employee(Adam Brown, Microsoft); employee.Print(); cout endl; Person* pPerson person; pPerson-Print(); // Calls Print in Person. cout endl; pPerson student; pPerson-Print(); // Calls Print in Student. cout endl; pPerson employee; pPerson-Print(); // Calls Print in Employee. }以下是类关系的mermaid流程图classDiagram class Person { -string m_stName Person(string stName) virtual void Print() const } class Student { -string m_stUniversity Student(string stName, string stUniversity) void Print() const } class Employee { -string m_stEmployer Employee(string stName, string stEmployer) void Print() const } Person |-- Student : Inheritance Person |-- Employee : Inheritance5. 抽象基类和纯虚方法5.1 抽象基类的概念抽象基类不能实例化为对象但可作为类层次结构的基类。若类中有至少一个纯虚方法该类就成为抽象类。// Person.h class Person { public: Person(const string stName); virtual void Print() const 0; protected: string m_stName; };// Person.cpp #include string using namespace std; #include Person.h Person::Person(const string stName) :m_stName(stName) { // Empty. }5.2 子类的实现由于Person是抽象类Student和Employee必须定义Print方法否则它们也会成为抽象类。// Student.h class Student : public Person { public: Student(const string stName, const string stUniversity); void Print() const; private: string m_stUniversity; };// Student.cpp #include string #include iostream using namespace std; #include Person.h #include Student.h Student::Student(const string stName, const string stUniversity) :Person(stName), m_stUniversity(stUniversity) { // Empty. } void Student::Print() const { cout Name: m_stName endl; cout University: m_stUniversity endl; }// Employee.h class Employee : public Person { public: Employee(const string stName, const string stEmployer); void Print() const; private: string m_stEmployer; };// Employee.cpp #include string #include iostream using namespace std; #include Person.h #include Employee.h Employee::Employee(const string stName, const string stEmployer) :Person(stName), m_stEmployer(stEmployer) { // Empty. } void Employee::Print() const { cout Name: m_stName endl; cout Company: m_stEmployer endl; }// Main.cpp #include string #include iostream using namespace std; #include Person.h #include Student.h #include Employee.h void main() { // Does not work as Person is an abstract class. // Person person(John Smith); // person.Print(); // cout endl; Student student(Mark Jones, Berkeley); student.Print(); cout endl; Employee employee(Adam Brown, Microsoft); employee.Print(); cout endl; // In this version, there is no object person to point at. // Person* pPerson person; // pPerson-Print(); // cout endl; Person* pPerson student; pPerson-Print(); // Calls Print in Student. cout endl; pPerson employee; pPerson-Print();// Calls Print in Employee. }6. 对象数组对象数组与值数组类似但要注意的是无法单独调用每个对象的构造函数所以类必须有默认构造函数或没有构造函数。// The default constructor is called for each car object. Car carArray[3]; carArray[2].IncreaseSpeed(100); // The default constructor is called for each car object. Car *pDynamicArray new Car[5]; pDynamicArray[4].IncreaseSpeed(100); delete [] pDynamicArray;也可以用列表初始化对象数组此时可以调用非默认构造函数。Car carArray[] {Car(), Car(100, 90)}; carArray[0].TurnLeft(90);7. 指针和链表指针可以指向对象和值类可以有指向另一个对象的指针作为成员变量从而构建链表。链表最后一个指针指向null。以下是链表结构的简单示意| 节点 | 值 | 指向下一节点的指针 || — | — | — || 1 | m_iValue | m_pNext || 2 | m_iValue | m_pNext || 3 | m_iValue | m_pNext || 末尾 | - | NULL |通过以上内容我们全面了解了C面向对象编程的多个重要方面包括类的定义、继承、多态、抽象类以及对象数组和链表的使用。这些知识是构建复杂C程序的基础希望能帮助大家更好地掌握C编程。C面向对象编程入门与进阶8. 总结与对比为了更好地理解上述各种概念下面通过表格对不同的类特性进行总结和对比。特性描述示例类代码体现构造函数用于初始化对象可重载有默认构造函数和带参数构造函数Car、BankAccount、Person等Car::Car()、Car::Car(int iSpeed, int iDirection)等析构函数用于释放动态分配的内存或关闭打开的文件一个类只有一个Car、BankAccount、Person等Car::~Car()等修饰器修改类的字段Carvoid Car::IncreaseSpeed(int iSpeed)等检查器查看类的字段Car、BankAccountint Car::GetSpeed()、int BankAccount::GetNumber() const等常量字段只能由构造函数初始化之后不能修改BankAccountconst int m_iNUMBER常量方法不能修改字段的值只有检查器可定义为常量方法BankAccountint BankAccount::GetNumber() const复制构造函数用于创建对象的副本BankAccountBankAccount(const BankAccount bankAccount)继承子类继承父类的公共和受保护成员Student、Employee继承Personclass Student : public Person等动态绑定通过虚函数实现根据实际对象调用相应方法Person、Student、Employeevirtual void Person::Print() const抽象基类不能实例化有纯虚函数Personvirtual void Print() const 0纯虚函数只有原型没有定义使类成为抽象类Personvirtual void Print() const 0对象数组类需有默认构造函数可列表初始化CarCar carArray[3];、Car carArray[] {Car(), Car(100, 90)};链表类有指向下一个对象的指针成员-节点包含m_pNext指针9. 实际应用建议在实际的C编程中为了更好地运用上述知识可参考以下建议-构造函数和析构函数确保在构造函数中正确初始化对象的字段避免未初始化的情况。在析构函数中释放动态分配的资源防止内存泄漏。-访问控制将类的字段设置为私有通过修饰器和检查器来访问和修改提高代码的封装性和安全性。-继承和多态合理使用继承来构建类层次结构将公共的属性和方法放在基类中提高代码的复用性。使用虚函数实现多态增强代码的灵活性。-抽象基类和纯虚函数当需要定义一些通用的接口但又不希望基类被实例化时使用抽象基类和纯虚函数。-对象数组和链表根据实际需求选择对象数组或链表。对象数组适合固定大小的对象集合链表适合动态添加和删除元素的场景。10. 代码优化思路在编写C面向对象代码时可以从以下几个方面进行优化-减少内存开销使用引用和指针来传递对象避免对象的复制。例如在构造函数中使用常量引用const string stName。-提高代码可读性遵循命名规范为类、方法和变量取有意义的名字。合理使用注释解释代码的功能和逻辑。-性能优化对于频繁调用的短方法可以考虑将其定义为内联函数减少函数调用的开销。例如BankAccount类中的Deposit和Withdraw方法。11. 错误处理与调试在编写和调试C面向对象代码时可能会遇到各种错误以下是一些常见错误及处理方法-编译错误-语法错误检查代码的语法如括号、分号、关键字的使用是否正确。-访问权限错误确保在访问类的私有成员时使用了正确的方法避免直接访问私有成员。-函数声明和定义不匹配检查函数的声明和定义是否一致包括参数列表和返回类型。-运行时错误-内存泄漏确保在析构函数中释放动态分配的内存使用智能指针可以有效避免内存泄漏。-空指针引用在使用指针之前检查指针是否为空避免空指针引用导致的程序崩溃。12. 未来拓展方向掌握了上述C面向对象编程的基础知识后可以进一步拓展学习以下内容-模板编程C的模板允许编写通用的代码提高代码的复用性。例如模板类和模板函数可以处理不同类型的数据。-标准模板库STLSTL提供了一系列的容器如vector、list、map等和算法如排序、查找等可以大大提高开发效率。-多线程编程在现代计算机中多线程编程可以充分利用多核处理器的性能。C提供了多线程库允许创建和管理线程。通过不断学习和实践我们可以深入掌握C面向对象编程的高级特性开发出更加高效、复杂的程序。希望大家在C编程的道路上不断前进取得更好的成果。以下是一个简单的mermaid流程图展示从基础类到抽象类和模板编程的学习路径graph LR A[基础类定义] -- B[继承与多态] B -- C[抽象基类与纯虚函数] C -- D[模板编程] D -- E[标准模板库STL] E -- F[多线程编程]通过以上内容我们对C面向对象编程有了更深入的理解和认识。无论是基础的类定义还是高级的模板编程和多线程编程都是C编程中不可或缺的部分。希望大家能够将这些知识运用到实际的项目中不断提升自己的编程能力。