2——of C++ class relative

C++类

C++和java都是面向对象的语言,所以类的语法上看起来相似,但也有些区别,比如访问控制符的书写规范。除此之外,在访问控制权限,静态static等内容也有很大区别

1.访问控制权限

  • 访问控制符
//不加的默认私有
class player {
 int x, y;
 int speed;
 void move(int a, int b){
     x += a * speed;
     y += b * speed;
 }
};
//加访问控制符
class player {
public:
 int x, y;
 int speed;
private:
 void move(int a, int b){
     x += a * speed;
     y += b * speed;
 }
};
  • 访问权限的继承

---- C++访问权限符有三种,public-可以任何位置访问类成员;protected-可以在子类(派生类中)访问父类成员;private-只能在自己类中访问成员
----类继承也包括public、protected和private继承

class player : public person {
...
};

ps:类继承后,成员的访问权限其实产生了一种"降级"效应。就比如原先的private权限访问度已经很低了,无论哪种权限继承,private成员都只能在本类中被访问;而对于像protected权限是为了让子类能访问到父类成员,比他高的public继承或者private继承都不会影响原先的效果,而private继承反倒会让它“降级”——即原本在父类的protected成员,经过private继承后在子类中变成了private成员;同理public成员也可能被protected继承或者private继承所“降级”

  • 对比java的权限访问符

相比较C++,java的访问权限符多了个default(缺省),并且各权限控制是针对包的管理。但java没有权限继承,这其实像是为了简化的一些骚操作,相似的规定就比如java也不能多继承(多继承就不能有super了)

static关键字的两种用法

  • 在类或结构体内使用static关键字修饰成员或方法,就表示静态成员或静态方法

  • 若是在类或结构体外部:若是静态全局变量,那这个全局变量就只声明在本cpp文件(翻译单元)中,且不能被别的extern导出;若是静态局部变量,那它的声明周期就相当于整个程序的声明周期,但作用范围被限制在本作用域内,ps:java没有静态局部变量

  • 同名的全局变量,则会导致重复声明的链接错误,要么通过static限制本cpp文件,要么通过extern外联其他同名全局变量

1.static解决

//a.cpp中
static int s_var = 5;

//main.cpp中
int s_var = 10;
int main(){
    std::cout << s_var << std::endl;
}

//输出10

2.extern解决

//a.cpp中
int s_var = 5;

//main.cpp中
extern int s_var;   //注意这里没有了赋值
int main(){
    std::cout << s_var << std::endl;
}

//输出5
//这被称为 external linkage或external linking。

this(and super-java单继承才有)

C++构造函数

class Entity {
public:
  int x, y;
  Entity(){}  //不带参数
  Entity(int x, int y) : x(x), y(y) {}  //带参数,用来初始化x和y

  void print()
  {
    std::cout << x << ',' << y << std::endl;
  }
};
  • 构造函数没有返回类型
  • 构造函数的命名必须和类名一样
  • 如果你不指定构造函数,你仍然有一个构造函数,这叫做默认构造函数(default constructor),是默认就有的。但是,我们仍然可以删除该默认构造函数:
class Log{
public:
    Log()=delete;
    ....
}
  • 构造函数不会在你没有实例化对象的时候运行,所以如果你只是使用类的静态方法,构造函数是不会执行的。
  • 当你用new关键字创建对象实例的时候也会调用构造函数。

ps:构造函数原理与java类中构造函数原理基本差不多,除了第一条的构造函数初始化表

C++析构函数

  • 析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。
  • 构造函数和析构函数在声明和定义的唯一区别就是放在析构函数前面的波形符(~)
/**以下在类内声明构造与析构函数,在类外定义**/

class Student {
private:
    int num;
    string name;
    char gender;
public:
    Student();
    Student(int num, string name, char gender);
    ~Student();
    void display();
};

// 无参构造
Student::Student() : num(-1), name("None"), gender('N') {}

Student::Student(int n, string p, char g) : num(n), name(p), gender(g) {
    cout << "执行构造函数: " << "Welcome, " << name << endl;
}

虚函数

作用就是为了实现多态(父类引用指向子类实例时,调用重名方法可以调用到子类重写的方法)

//基类
class Entity
{
public:
    virtual std::string GetName() {return "Entity";} //第一步,定义基类,声明基类函数为 virtual的。
};

//派生类
class Player : public Entity
{
private: 
    std::string m_Name; 
public: 
    Player(const std::string& name):m_Name (name) {} 
    //第二步,定义派生类(继承基类),派生类实现了定义在基类的 virtual 函数。
    std::string GetName() override {return m_Name;}  //C++11新标准允许给被重写的函数用"override"关键字标记,增强代码可读性。
};

void printName(Entity* entity){
    std::cout << entity -> GetName() << std::endl;
}

int main(){
    Entity* e = new Entity();
    printName(e); 
    //第三步,声明基类指针,并指向派生类,调用`virtual`函数,此时虽然是基类指针,但调用的是派生类实现的基类virtual函数。Entity* p = new Player("cherno");也可以
    Player* p = new Player("cherno"); 
    printName(p); 
}

纯虚函数

类似于java中的接口,只声明方法但没有具体实现,被继承(实现)时子类必须定义其方法
声明方法: 在基类中纯虚函数的方法的后面加 =0
其中特别声明一点,假设父类在实现接口之后,子类或后续子孙类在继承于父类或祖先类,便可以不用强制实现接口方法。当然子孙类实现接口方法,便属于是重写父类已实现的接口方法了

class Printable{   //接口。其实就是个类。之所以称它为接口,只是因为它有一个纯虚函数,仅此而已。
public:
    virtual std::string GetClassName()= 0;
};
//基类
class Entity : public Printable
{
public:
    virtual std::string GetName() {return "Entity";}
 std::string GetClassName() override {return "Entity";} //实现接口的纯虚函数
};

//派生类
class Player : public Entity //因为Player已经是Entity(已有接口),所以Player不用去实现Printable接口
{
private: 
 std::string m_Name; 
public: 
 Player(const std::string& name):m_Name (name) {} 
 std::string GetName() override {return m_Name;} 
 std::string GetClassName() override {return "Player";} //实现接口的纯虚函数
};
posted @ 2023-10-16 22:32  JayerListen  阅读(7)  评论(0编辑  收藏  举报