1.类和成员声明,定义,初始化的基本规则

C++中类的基本模板如下:

namespace 空间命名{//可以定义namespace,也可以不定义
    class/struct 类名称{
        基本成员;
        构造函数():成员初始化列表{
            构造函数主体;
        }
    };
}

例如:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
//Person.h
#pragma once
#include <string>
using namespace std;
class Person{
    private://定义私有成员
        string name;
        int age;
    public://定义公共成员
        Person() = default;//c++11标准中使用=default,定义构造函数的默认行为
        Person(string nm,int ag) : name(nm),age(ag){}//带两个参数的构造函数
        Person(string nm) : name(nm){}//带一个参数的构造函数
        Person(int ag) : age(ag){}
        /*
 *          或者写成:
 *                  Person(string nm) : Person(nm,0){}//调用带两个参数的构造函数,初始化age为0
 *                          Person(int ag) : Person("",ag){}//调用有两个参数的构造函数,初始化name为""
 *                                  */
        
        void setName(string name){
            this->name = name;
        }
        string getName(){
            return this->name;
        }

        void setAge(int age){
            this->age = age;
        }
        int getAge(){
            return this->age;
        }
};
//PersonTest.cpp
#include "Person.h"
#include <iostream>
using namespace std;

int main(int argc, char * argv[]){
    Person person("jamy",20), *p = &person;
    cout << "name:" << p->getName() << "\n"
        << "age:" << p->getAge() << endl;
    
return 0;
}

在定义类的时候,可以使用class关键字或struct关键字。这种变化仅仅是形式上有所不同,实际上我们可以使用这两个关键字中的任何一个定义类。唯一的区别是struct和class的默认访问权限不太一样。如果我们使用struct关键字,则定义在第一个访问说明符之前的成员是public的;相反,如果我们使用class关键字,则这些成员是private的。
出于统一编程的考虑,当我们希望定义的类的所有成员是public的时,使用struct;反之,如果希望成员是private的,使用class。

构造函数的名字和类名相同。和其他函数不一样的是,构造函数没有返回类型;构造函数也有一个(可能为空的)参数列表和一个(可能为空的)函数体。构造函数的初始值是成员名字的一个列表,每个名字后面紧跟括起来的成员初始值,不同成员的初始值通过逗号分隔开来。例如上面的:

        Person(string nm,int ag) : name(nm),age(ag){}

其中name(nm),age(ag){},表示初始name成员为nm值,初始age成员为ag值,函数体为空。在函数体中,也可以改变参数的值:

        Person(string nm,int ag){
            this->name = nm;//赋值,并非初始化
            this->age = ag;//赋值,并非初始化
        }

但上面这段代码并没有初始化name和age值,他们只是重新修改name和age的值。并且有些特殊成员(例如引用和constexpr)是不运行这种方式的,所以建议使用初始化的方式。

 

2.this使用的注意点

成员函数通过一个名为this的额外隐式参数来访问调用它的那个对象,当我们调用一个成员函数时,用请求该函数的对象地址初始化this。
例如:

person.getName();

则编译器负责把total的地址传递给person的隐式形参this,可以隐式的认为编译器将该调用重写成了如下的形式:

Person::getName(&person);

其中调用Person的getName成员传入了person对象的地址。

默认情况下,this的类型是指向类类型非常量版本的的常量指针。在Person的类型中,this的默认类型是Person *const。

this的默认类型是Person *const,那么有没有其它的类型呢?答案是肯定的,当我们在定义函数的时候指定const关键字,那么this就是指向类类型常量版本的常量指针,在Person类中也就是 const Person * const类型。

void getName() const{//只能读取属性的值,不能改变属性的值
    return this->name;//this的类型是const Person * const
}

 

3.静态成员

和其他成员函数一样,我们既可以在类的内部也可以在类的外部定义静态成员函数。当在类的外部定义静态成员函数时,不能重复static关键字,该关键字只出现在类内部的声明语句。

因为静态数据成员不属于类的任何一个对象,所在它们并不是在创建类的对象时被定义的,这意味着它们不是由类的构造函数初始化的。而且一般来说,我们不能在类的内部初始化静态成员。相反的,必须在类的外部定义和初始化每个静态成员。但如果给静态成员加上constexpr,那么就可以在类内初始化了。

在类外的定义中,定义静态数据成员的方式和定义成员函数差不多,需要指定对象的类型名,类名,作用域运算符以及成员函数的名字:
数据类型 类名::静态成员名 = 初始值

//Account.h
class Account{
    public:
        static double rate(){return interestRate;}
        static void rate(double);
    private:
        static double interestRate;//不能有初始值,不能在类内部初始化 static 成员
        static constexpr int period = 30;//可以在类内部初始化 static constexpr 成员
        double daily_tbl[period];
}
//Account.cpp
#include "Account.h"

double Account::interestRate = rate();//初始化静态成员interestRate,不能再次使用static关键字

double void Account::rate(double newRate){//初始化静态函数rate,不能再次使用static关键字
    interestRate = newRate;
}

 



扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄