【C++】C++中类的基本使用

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

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

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

例如:

//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;
  //也可以写成:Person person = Person("jamy",20);
    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使用的注意点

需要注意在C++中,this不是代表本类对象,而是指向本类对象的指针。在使用的需要注意,this是一个指针。

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

person.getName();

则编译器负责把person的地址传递给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 成员
};
//Account.cpp
#include "Account.h"

double Account::interestRate = rate();//初始化静态成员interestRate,不能再次使用static关键字。这里等同于double Account::interestRate = interestRate。经过interestRate的赋值后,interestRate的值就是0.

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

上面案例中,Account::interestRate = rate()语句相当于Account::interestRate = interestRate,当静态变量定义后就会分配内存空间。这里interestRate是int类型,所以默认值为0。

 

下面的案例有比较清晰的解释:

    #include <stdio.h>
    class A {
        public:
            static int a; //声明但未定义
     };
    int main() {
        printf("%d", A::a);
        return 0;
    }

编译以上代码会出现“对‘A::a’未定义的引用”错误。这是因为静态成员变量a未定义,也就是还没有分配内存,显然是不可以访问的。

    #include <stdio.h>
    class A {
        public:
            static int a; //声明但未定义
     };
    int A::a = 3; //定义了静态成员变量,同时初始化。也可以写"int A:a;",即不给初值,同样可以通过编译
    int main() {
        printf("%d", A::a);
        return 0;
    }

   这样就对了,因为给a分配了内存,所以可以访问静态成员变量a了。

   注意:在类外面  这样子写 :int A::a ; 也可以表示已经定义了。



转载于:https://www.cnblogs.com/HDK2016/p/10667501.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值