C++面向对象

打印 上一主题 下一主题

主题 1043|帖子 1043|积分 3129

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
参考:
  C++ 类 & 对象 | 菜鸟教程 (runoob.com) 
    C++ 在 C 语言的底子上增加了面向对象编程,C++ 支持面向对象程序计划。类是 C++ 的核心特性,通常被称为用户界说的类型(本质就是一种数据类型)。
  类用于指定对象的形式,是一种用户自界说的数据类型,它是一种封装了数据和函数的组合。类中的数据称为成员变量,函数称为成员函数。类可以被看作是一种模板,可以用来创建具有雷同属性和行为的多个对象。
  实在就是一种布局体类型界说、布局体变量,布局体指针。
  类界说

   界说一个类须要使用关键字 class,然后指定类的名称,并类的主体是包含在一对花括号中,主体包含类的成员变量和成员函数。
  界说一个类,本质上是界说一个数据类型的蓝图,它界说了类的对象包罗了什么,以及可以在这个对象上实行哪些操作。
  

  以下实例我们使用关键字 class 界说 Box 数据类型,包含了三个成员变量 length、breadth 和 height:
  1. class Box
  2. {
  3.    public:
  4.       double length;   // 盒子的长度
  5.       double breadth;  // 盒子的宽度
  6.       double height;   // 盒子的高度
  7. };
复制代码
关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。您也可以指定类的成员为 privateprotected,这个我们稍后会举行解说。
  界说对象

   类提供了对象的蓝图,以是基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。下面的语句声明确类 Box 的两个对象:
  1. Box Box1; // 声明 Box1,类型为 Box
  2. Box Box2; // 声明 Box2,类型为 Box
复制代码
对象 Box1 和 Box2 都有它们各自的数据成员。
  实在可以类比布局体类型以及布局体变量。
  访问类成员

   类的对象的公共数据成员可以使用直接成员访问运算符 . 来访问。
  

  为了更好地明白这些概念,让我们尝试一下下面的实例:
  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5.    public:
  6.       double length;   // 长度
  7.       double breadth;  // 宽度
  8.       double height;   // 高度
  9.       // 成员函数声明
  10.       double get(void);
  11.       void set( double len, double bre, double hei );
  12. };
  13. // 成员函数定义
  14. double Box::get(void)
  15. {
  16.     return length * breadth * height;
  17. }
  18. void Box::set( double len, double bre, double hei)
  19. {
  20.     length = len;
  21.     breadth = bre;
  22.     height = hei;
  23. }
  24. int main( )
  25. {
  26.    Box Box1;        // 声明 Box1,类型为 Box
  27.    Box Box2;        // 声明 Box2,类型为 Box
  28.    Box Box3;        // 声明 Box3,类型为 Box
  29.    double volume = 0.0;     // 用于存储体积
  30.    // box 1 详述
  31.    Box1.height = 5.0;
  32.    Box1.length = 6.0;
  33.    Box1.breadth = 7.0;
  34.    // box 2 详述
  35.    Box2.height = 10.0;
  36.    Box2.length = 12.0;
  37.    Box2.breadth = 13.0;
  38.    // box 1 的体积
  39.    volume = Box1.height * Box1.length * Box1.breadth;
  40.    cout << "Box1 的体积:" << volume <<endl;
  41.    // box 2 的体积
  42.    volume = Box2.height * Box2.length * Box2.breadth;
  43.    cout << "Box2 的体积:" << volume <<endl;
  44.    // box 3 详述
  45.    Box3.set(16.0, 8.0, 12.0);
  46.    volume = Box3.get();
  47.    cout << "Box3 的体积:" << volume <<endl;
  48.    return 0;
  49. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Box1 的体积:210
  2. Box2 的体积:1560
  3. Box3 的体积:1536
复制代码
须要注意的是,私有的成员和受保护的成员不能使用直接成员访问运算符 (.) 来直接访问。我们将在后续的教程中学习如何访问私有成员和受保护的成员。
  类成员函数界说

   成员函数可以界说在类界说内部,或者单独使用范围解析运算符 :: 来界说。
  您可以按照如下方式界说 getVolume() 函数:
  1. class Box
  2. {
  3.    public:
  4.       double length;      // 长度
  5.       double breadth;     // 宽度
  6.       double height;      // 高度
  7.    
  8.       double getVolume(void)
  9.       {
  10.          return length * breadth * height;
  11.       }
  12. };
复制代码
您也可以在类的外部使用范围解析运算符 :: 界说该函数,如下所示:
  1. double Box::getVolume(void)
  2. {
  3.     return length * breadth * height;
  4. }
复制代码
 在这里,须要夸大一点,在 :: 运算符之前必须使用类名。
  这种界说格式为:
  1. 返回值 类名::函数名(形参)
复制代码
关于范围解析运算符:
  在C++中,:: 被称为范围解析运算符(scope resolution operator),也被称为双冒号运算符。它在多种情况下用于明确指出标识符的作用域,这在C++中是非常紧张的,尤其是当存在命名辩论或者须要从特定作用域访问标识符时。
  更多参考:C++ ::范围解析运算符介绍_c++中的范围解析运算符-CSDN博客
  类访问修饰符

   数据封装是面向对象编程的一个紧张特点,它防止函数直接访问类类型的内部成员。类成员的访问限定是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。
  1. class Base {
  2.    public:
  3.   // 公有成员
  4.    protected:
  5.   // 受保护成员
  6.    private:
  7.   // 私有成员
  8. };
复制代码
一个类可以有多个 public、protected 或 private 标记区域。每个标记区域在下一个标记区域开始之前或者在遇到类主体竣事右括号之前都是有效的。
  !!!!!!!!!!!!!!成员和类的默认访问修饰符是 private。
  公有(public)成员

   公有成员在程序中类的外部是可访问的。您可以不使用任何成员函数来设置和获取公有变量的值,如下所示:
  1. #include <iostream>
  2. using namespace std;
  3. class Line
  4. {
  5.    public:
  6.       double length;
  7.       void setLength( double len );
  8.       double getLength( void );
  9. };
  10. // 成员函数定义
  11. double Line::getLength(void)
  12. {
  13.     return length ;
  14. }
  15. void Line::setLength( double len )
  16. {
  17.     length = len;
  18. }
  19. // 程序的主函数
  20. int main( )
  21. {
  22.    Line line;
  23.    // 设置长度
  24.    line.setLength(6.0);
  25.    cout << "Length of line : " << line.getLength() <<endl;
  26.    // 不使用成员函数设置长度
  27.    line.length = 10.0; // OK: 因为 length 是公有的
  28.    cout << "Length of line : " << line.length <<endl;
  29.    return 0;
  30. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Length of line : 6 Length of line : 10
复制代码
更多待补充。
  私有(private)成员

   私有成员变量或函数在类的外部是不可访问的,乃至是不可查看的。只有类和友元函数可以访问私有成员。
  默认情况下,类的全部成员都是私有的。比方在下面的类中,width 是一个私有成员,这意味着,如果您没有使用任何访问修饰符,类的成员将被假定为私有成员:
  1. class Box
  2. {
  3.    double width;
  4.    public:
  5.       double length;
  6.       void setWidth( double wid );
  7.       double getWidth( void );
  8. };
复制代码
实际操作中,我们一般会在私有区域界说数据,在公有区域界说相关的函数,以便在类的外部也可以调用这些函数,如下所示:
  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5.    public:
  6.       double length;
  7.       void setWidth( double wid );
  8.       double getWidth( void );
  9.    private:
  10.       double width;
  11. };
  12. // 成员函数定义
  13. double Box::getWidth(void)
  14. {
  15.     return width ;
  16. }
  17. void Box::setWidth( double wid )
  18. {
  19.     width = wid;
  20. }
  21. // 程序的主函数
  22. int main( )
  23. {
  24.    Box box;
  25.    // 不使用成员函数设置长度
  26.    box.length = 10.0; // OK: 因为 length 是公有的
  27.    cout << "Length of box : " << box.length <<endl;
  28.    // 不使用成员函数设置宽度
  29.    // box.width = 10.0; // Error: 因为 width 是私有的
  30.    box.setWidth(10.0);  // 使用成员函数设置宽度
  31.    cout << "Width of box : " << box.getWidth() <<endl;
  32.    return 0;
  33. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Length of box : 10 Width of box : 10
复制代码
注意,类内访问,就真的是在class类内,即使是一个该class的对象也无法直接访问私有数据。
  受保护(protected)成员

   protected(受保护)成员变量或函数与私有成员十分相似,但有一点差别,protected(受保护)成员在派生类(即子类)中是可访问的。
  下面的实例与前面的实例雷同,在这里 width 成员可被派生类 smallBox 的任何成员函数访问。
  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5.    protected:
  6.       double width;
  7. };
  8. class SmallBox:Box // SmallBox 是派生类
  9. {
  10.    public:
  11.       void setSmallWidth( double wid );
  12.       double getSmallWidth( void );
  13. };
  14. // 子类的成员函数
  15. double SmallBox::getSmallWidth(void)
  16. {
  17.     return width ;
  18. }
  19. void SmallBox::setSmallWidth( double wid )
  20. {
  21.     width = wid;
  22. }
  23. // 程序的主函数
  24. int main( )
  25. {
  26.    SmallBox box;
  27.    // 使用成员函数设置宽度
  28.    box.setSmallWidth(5.0);
  29.    cout << "Width of box : "<< box.getSmallWidth() << endl;
  30.    return 0;
  31. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Width of box : 5
复制代码
更多待补充。
  
类的构造函数

   类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时实行。
  构造函数的名称与类的名称是完全雷同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
  下面的实例有助于更好地明白构造函数的概念:
  1. #include <iostream>
  2. using namespace std;
  3. class Line
  4. {
  5.    public:
  6.       void setLength( double len );
  7.       double getLength( void );
  8.       Line();  // 这是构造函数
  9.    private:
  10.       double length;
  11. };
  12. // 成员函数定义,包括构造函数
  13. Line::Line(void)
  14. {
  15.     cout << "Object is being created" << endl;
  16. }
  17. void Line::setLength( double len )
  18. {
  19.     length = len;
  20. }
  21. double Line::getLength( void )
  22. {
  23.     return length;
  24. }
  25. // 程序的主函数
  26. int main( )
  27. {
  28.    Line line;
  29.    // 设置长度
  30.    line.setLength(6.0);
  31.    cout << "Length of line : " << line.getLength() <<endl;
  32.    return 0;
  33. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Object is being created Length of line : 6
复制代码
更多待补充。 
  带参数的构造函数

   默认的构造函数没有任何参数,但如果须要,构造函数也可以带有参数。这样在创建对象时就会给对象赋初始值,如下面的例子所示:
  1. #include <iostream>
  2. using namespace std;
  3. class Line
  4. {
  5.    public:
  6.       void setLength( double len );
  7.       double getLength( void );
  8.       Line(double len);  // 这是构造函数
  9.    private:
  10.       double length;
  11. };
  12. // 成员函数定义,包括构造函数
  13. Line::Line( double len)
  14. {
  15.     cout << "Object is being created, length = " << len << endl;
  16.     length = len;
  17. }
  18. void Line::setLength( double len )
  19. {
  20.     length = len;
  21. }
  22. double Line::getLength( void )
  23. {
  24.     return length;
  25. }
  26. // 程序的主函数
  27. int main( )
  28. {
  29.    Line line(10.0);
  30.    // 获取默认设置的长度
  31.    cout << "Length of line : " << line.getLength() <<endl;
  32.    // 再次设置长度
  33.    line.setLength(6.0);
  34.    cout << "Length of line : " << line.getLength() <<endl;
  35.    return 0;
  36. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Object is being created, length = 10
  2. Length of line : 10
  3. Length of line : 6
复制代码
!!!!!!!!!千万注意:构造函数没有返回值。 
  使用初始化列表来初始化字段

   使用初始化列表来初始化字段: 
  1. Line::Line( double len): length(len)
  2. {
  3.     cout << "Object is being created, length = " << len << endl;
  4. }
复制代码
上面的语法等同于如下语法:
  1. Line::Line( double len)
  2. {
  3.     length = len;
  4.     cout << "Object is being created, length = " << len << endl;
  5. }
复制代码
假设有一个类 C,具有多个字段 X、Y、Z 等须要举行初始化,同理地,您可以使用上面的语法,只须要在差别的字段使用逗号举行分隔,如下所示:
  1. C::C( double a, double b, double c): X(a), Y(b), Z(c)
  2. {
  3.   ....
  4. }
复制代码

  类的析构函数

   类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时实行。
  析构函数的名称与类的名称是完全雷同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(好比关闭文件、开释内存等)前开释资源。
  下面的实例有助于更好地明白析构函数的概念:
  1. #include <iostream>
  2. using namespace std;
  3. class Line
  4. {
  5.    public:
  6.       void setLength( double len );
  7.       double getLength( void );
  8.       Line();   // 这是构造函数声明
  9.       ~Line();  // 这是析构函数声明
  10.    private:
  11.       double length;
  12. };
  13. // 成员函数定义,包括构造函数
  14. Line::Line(void)
  15. {
  16.     cout << "Object is being created" << endl;
  17. }
  18. Line::~Line(void)
  19. {
  20.     cout << "Object is being deleted" << endl;
  21. }
  22. void Line::setLength( double len )
  23. {
  24.     length = len;
  25. }
  26. double Line::getLength( void )
  27. {
  28.     return length;
  29. }
  30. // 程序的主函数
  31. int main( )
  32. {
  33.    Line line;
  34.    // 设置长度
  35.    line.setLength(6.0);
  36.    cout << "Length of line : " << line.getLength() <<endl;
  37.    return 0;
  38. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Object is being created
  2. Length of line : 6
  3. Object is being deleted
复制代码
注意,析构函数不仅没有返回值,也没有参数。 
  友元函数

   类的友元函数是界说在类外部,但有权访问类的全部私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的界说中出现过,但是友元函数并不是成员函数。
  友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其全部成员都是友元。
  如果要声明函数为一个类的友元,须要在类界说中该函数原型前使用关键字 friend,如下所示:
  1. class Box
  2. {
  3.    double width;
  4. public:
  5.    double length;
  6.    friend void printWidth( Box box );
  7.    void setWidth( double wid );
  8. };
复制代码
声明类 ClassTwo 的全部成员函数作为类 ClassOne 的友元,须要在类 ClassOne 的界说中放置如下声明:
  1. friend class ClassTwo;
复制代码
更多待补充。 
  this 指针

   在 C++ 中,this 指针是一个特殊的指针,它指向当前对象的实例。
  在 C++ 中,每一个对象都能通过 this 指针来访问自己的地点。
  this是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。
  当一个对象的成员函数被调用时,编译器会隐式地通报该对象的地点作为 this 指针。
  友元函数没有 this 指针,由于友元不是类的成员,只有成员函数才有 this 指针。
  下面的实例有助于更好地明白 this 指针的概念:
  1. #include <iostream>
  2. class MyClass {
  3. private:
  4.     int value;
  5. public:
  6.     void setValue(int value) {
  7.         this->value = value;
  8.     }
  9.     void printValue() {
  10.         std::cout << "Value: " << this->value << std::endl;
  11.     }
  12. };
  13. int main() {
  14.     MyClass obj;
  15.     obj.setValue(42);
  16.     obj.printValue();
  17.     return 0;
  18. }
复制代码
实例解析:
  

  • 以上实例中,我们界说了一个名为 MyClass 的类,它有一个私有成员变量 value。
  • 类中的 setValue() 函数用于设置 value的 值,而 printValue() 函数用于打印 value 的值。
  • 在 setValue() 函数中,我们使用 this 指针来引用当前对象的成员变量 value,并将传入的值赋给它,这样可以明确地告诉编译器我们想要访问当前对象的成员变量,而不是函数参数或局部变量。
  • 在 printValue() 函数中,我们同样使用 this 指针来引用当前对象的成员变量 value,并将其打印出来。
  • 在 main() 函数中,我们创建了一个 MyClass 的对象 obj,然后使用 setValue() 函数设置 value 的值为 42,并通过 printValue() 函数打印出来。
  • 通过使用 this 指针,我们可以在成员函数中访问当前对象的成员变量,即使它们与函数参数或局部变量同名,这样可以克制命名辩论,并确保我们访问的是正确的变量。
  指向类的指针

   类比布局体指针。 
  一个指向 C++ 类的指针与指向布局的指针雷同,访问指向类的指针的成员,须要使用成员访问运算符 ->,就像访问指向布局的指针一样。与全部的指针一样,您必须在使用指针之前,对指针举行初始化。
  在 C++ 中,指向类的指针指向一个类的对象,与平凡的指针相似,指向类的指针可以用于访问对象的成员变量和成员函数。
  声明和初始化指向类的指针
  1. #include <iostream>
  2. class MyClass {
  3. public:
  4.     int data;
  5.     void display() {
  6.         std::cout << "Data: " << data << std::endl;
  7.     }
  8. };
  9. int main() {
  10.     // 创建类对象
  11.     MyClass obj;
  12.     obj.data = 42;
  13.     // 声明和初始化指向类的指针
  14.     MyClass *ptr = &obj;
  15.     // 通过指针访问成员变量
  16.     std::cout << "Data via pointer: " << ptr->data << std::endl;
  17.     // 通过指针调用成员函数
  18.     ptr->display();
  19.     return 0;
  20. }
复制代码
当上面的代码被编译和实行时,它会产生下列效果:
  1. Data via pointer: 42
  2. Data: 42
复制代码
动态分配内存
  指向类的指针还可以用于动态分配内存,创建类的对象:
  1. #include <iostream>
  2. class MyClass {
  3. public:
  4.     int data;
  5.     void display() {
  6.         std::cout << "Data: " << data << std::endl;
  7.     }
  8. };
  9. int main() {
  10.     // 动态分配内存创建类对象
  11.     MyClass *ptr = new MyClass;
  12.     ptr->data = 42;
  13.     // 通过指针调用成员函数
  14.     ptr->display();
  15.     // 释放动态分配的内存
  16.     delete ptr;
  17.     return 0;
  18. }
复制代码
指向类的指针可以作为函数参数通报
  1. #include <iostream>
  2. class MyClass {
  3. public:
  4.     int data;
  5.     void display() {
  6.         std::cout << "Data: " << data << std::endl;
  7.     }
  8. };
  9. // 函数接受指向类的指针作为参数
  10. void processObject(MyClass *ptr) {
  11.     ptr->display();
  12. }
  13. int main() {
  14.     MyClass obj;
  15.     obj.data = 42;
  16.     // 将指向类的指针传递给函数
  17.     processObject(&obj);
  18.     return 0;
  19. }
复制代码
实在就和布局体指针用法雷同。
  类的静态成员

   我们可以使用 static 关键字来把类成员界说为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。
  

  静态成员在类的全部对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,全部的静态数据都会被初始化为零。我们不能把静态成员的初始化放置在类的界说中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它举行初始化,如下面的实例所示。
  下面的实例有助于更好地明白静态成员数据的概念:
  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5.    public:
  6.       static int objectCount;
  7.       // 构造函数定义
  8.       Box(double l=2.0, double b=2.0, double h=2.0)
  9.       {
  10.          cout <<"Constructor called." << endl;
  11.          length = l;
  12.          breadth = b;
  13.          height = h;
  14.          // 每次创建对象时增加 1
  15.          objectCount++;
  16.       }
  17.       double Volume()
  18.       {
  19.          return length * breadth * height;
  20.       }
  21.    private:
  22.       double length;     // 长度
  23.       double breadth;    // 宽度
  24.       double height;     // 高度
  25. };
  26. // 初始化类 Box 的静态成员
  27. int Box::objectCount = 0;
  28. int main(void)
  29. {
  30.    Box Box1(3.3, 1.2, 1.5);    // 声明 box1
  31.    Box Box2(8.5, 6.0, 2.0);    // 声明 box2
  32.    // 输出对象的总数
  33.    cout << "Total objects: " << Box::objectCount << endl;
  34.    return 0;
  35. }
复制代码
静态成员函数
  如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
  静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。
  静态成员函数有一个类范围,他们不能访问类的 this 指针。您可以使用静态成员函数来判定类的某些对象是否已被创建。
  静态成员函数与平凡成员函数的区别:
  

  • 静态成员函数没有 this 指针,只能访问静态成员(包罗静态成员变量和静态成员函数)。
  • 平凡成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。
  下面的实例有助于更好地明白静态成员函数的概念:
  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5.    public:
  6.       static int objectCount;
  7.       // 构造函数定义
  8.       Box(double l=2.0, double b=2.0, double h=2.0)
  9.       {
  10.          cout <<"Constructor called." << endl;
  11.          length = l;
  12.          breadth = b;
  13.          height = h;
  14.          // 每次创建对象时增加 1
  15.          objectCount++;
  16.       }
  17.       double Volume()
  18.       {
  19.          return length * breadth * height;
  20.       }
  21.       static int getCount()
  22.       {
  23.          return objectCount;
  24.       }
  25.    private:
  26.       double length;     // 长度
  27.       double breadth;    // 宽度
  28.       double height;     // 高度
  29. };
  30. // 初始化类 Box 的静态成员
  31. int Box::objectCount = 0;
  32. int main(void)
  33. {
  34.   
  35.    // 在创建对象之前输出对象的总数
  36.    cout << "Inital Stage Count: " << Box::getCount() << endl;
  37.    Box Box1(3.3, 1.2, 1.5);    // 声明 box1
  38.    Box Box2(8.5, 6.0, 2.0);    // 声明 box2
  39.    // 在创建对象之后输出对象的总数
  40.    cout << "Final Stage Count: " << Box::getCount() << endl;
  41.    return 0;
  42. }
复制代码
更多待补充。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

圆咕噜咕噜

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表