C++学习笔记第三天:类、虚函数、双冒号

简介: 类 class Box { public: double length; // 盒子的长度 double breadth; // 盒子的宽度 double height; // 盒子的高度 }; 类成员的作用域: public:公共成员。

class Box
{
   public:
      double length;   // 盒子的长度
      double breadth;  // 盒子的宽度
      double height;   // 盒子的高度
};

类成员的作用域:

public:公共成员。访问权限:外部、子类、本身

protected:受保护成员。访问权限:子类、本身

private:私有成员。访问权限:本身

 

构造函数

跟其他语言一样,使用类名作为函数名,无返回值,可以有参数。

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();  // 这是构造函数
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line;
 
   // 设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

如果是带参数的构造函数,可以使用初始化列表:

Line::Line( double len): length(len)
{
    cout << "Object is being created, length = " << len << endl;
}

上面的语法等同于如下语法:

Line::Line( double len)
{
    cout << "Object is being created, length = " << len << endl;
    length = len;
}

如果有多个参数,中间用逗号隔开:

Line::Line( double len): length(len), para02(var02)
{
    cout << "Object is being created, length = " << len << endl;
}

另外,初始化列表并不是构造函数专用的,类的普通成员函数也可以使用。

 

析构函数

这个挺新鲜的,作用跟构造函数正好相反,在对象被销毁的时候执行。

无返回值,无参数,所以无法重载,一个类只能有一个析构函数

函数名也是与类同名,只需要在前面加一个波浪线前桌:~

在析构函数中,主要用来销毁在构造函数或成员方法里 new 出来的对象或指针,最常用的就是:delete obj

#include <stdio.h>  
#include <iostream>  
#include <vector>  
using namespace std;  

struct CP  
{  
    int a;  
    int b;  
};  

class TEST  
{  
    public:  
        CP* compound;  
        int num;  
    TEST(){  
        compound = new CP();  
        cout << "create a new TEST obj" << endl;  
    };  
    ~TEST(){  
        cout << "delete TEST obj" << endl;  
        delete compound;  
    };  
};  

 

类的继承

跟JAVA不同,C++中允许一个类继承多个父类:

#include <iostream>
 
using namespace std;
 
// 基类 Shape
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
 
// 基类 PaintCost
class PaintCost 
{
   public:
      int getCost(int area)
      {
         return area * 70;
      }
};
 
// 派生类
class Rectangle: public Shape, public PaintCost
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
 
int main(void)
{
   Rectangle Rect;
   int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
 
   area = Rect.getArea();
   
   // 输出对象的面积
   cout << "Total area: " << Rect.getArea() << endl;
 
   // 输出总花费
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;
 
   return 0;
}

输出:

Total area: 35
Total paint cost: $2450

 

虚函数

这个不太好理解,只能按照别人的描述硬性记忆:在类的成员函数前面加 virtual 表示该成员函数为虚函数。

虚函数在C++中的作用不低,很多官方的源码中都存在大量的虚函数

目前位置能理解的作用包括:

1、允许用基类的指针来调用子类的这个函数:

class A  
{  
    public:  
        virtual void foo()  
        {  
            cout<<"A::foo() is called"<<endl;  
        }  
};  
class B : public A  
{  
    public:  
        void foo()  
        {  
            cout<<"B::foo() is called"<<endl;  
        }  
};  
int main(void)  
{  
    A *a = new B();  
    a->foo();   // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!  
    return 0;  
}

 

2、通过“纯虚函数”实现抽象类

虚函数:

virtual ReturnType funtion1(params...);

虚函数在基类中可以有默认实现,派生类也可以覆盖;

但如果在基类中没有默认实现,那么派生类必须具体实现。

 

纯虚函数:

virtual ReturnType funtion1(params...)=0; 

在虚函数声明的后面加“=0”就表示这是一个纯虚函数,含有纯虚函数的类成为抽象类。

纯虚函数用来规范派生类的行为,即接口。派生类中必须对这个纯虚函数进行具体实现。

抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。

 

对虚函数的理解,有一个很好的比方:

比如你有个游戏,里面有个含有纯虚函数 [攻击] 的抽象类 [怪物],然后有三个派生子类 [狼][蜘蛛][蛇] 都继承了 [怪物],并且都各自实现了自己独特的 [攻击] 函数。

那在出现怪物的时候就可以定义一个 虚基类指针数组,把各种怪物的指针给它,然后迭代循环的时候直接:怪物[i]->攻击() 攻击玩家就行了

Monster *pMonster[3];
pMonster[0] = new Wolf(); //初始化一匹狼
pMonster[1] = new Spider(); //初始化一只蜘蛛
pMonster[2] = new Snake(); //初始化一条蛇

for(int i=0; i<3; i++){
    pMonster[i] -> attack(); //攻击
}

 

双冒号(::)

1、调用 namespace 中的成员时,需要用 ::

2、在类的外部定义成员函数时,需要用::

3、区别两个类中同名的成员变量或者函数时,需要用::

4、在成员函数内部调用同名的全局变量时,需要用::

5、调用类的静态成员函数时,可以用::


宠辱不惊,看庭前花开花落;去留无意,望天上云卷云舒
目录
相关文章
|
5天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
25 5
|
11天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
40 4
|
12天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
36 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4
|
1月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
24 4
|
1月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
1月前
|
存储 编译器 C语言
【C++打怪之路Lv3】-- 类和对象(上)
【C++打怪之路Lv3】-- 类和对象(上)
17 0
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
1月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)
|
1月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
53 1