类的私有成员、this指针、const对象、静态成员、类对象的指针和引用

类的私有成员

定义类成员时使用关键字private,私有类成员只能被类的成员函数访问。

必要时,public函数成员可以提供对包括private成员在内的所有类成员的间接访问。

如果没有另外指定,默认访问特性是private。

#include <iostream>
#include <iomanip>
#include <string>

class CPerson
{
//private: 可以省略
    std::string name;
    int age;
    void showmsg()
    {
        std::cout << name << "'age is " << age << std::endl;        
    }

public:    
    void show()
    {
        std::cout << "show() is called" << std::endl;
        showmsg();
    }
    CPerson(int age = 4, std::string name = "tiger") :age{age},name{name}
    {
        std::cout <<  "Constructor called "<< std::endl;
    }
};

int main()
{
    CPerson person1;
    //person1.showmsg();    //私有成员不能被访问
    person1.show();
}

访问私有类成员

public函数成员可以提供对包括private成员在内的所有类成员的间接访问。

#include <iostream>
#include <iomanip>
#include <string>

class CPerson
{
//private: 可以省略
    std::string name;
    int age;
    void showmsg()
    {
        std::cout << name << "'age is " << age << std::endl;        
    }

public:
    inline int getAge()
    {
        return age;
    }
    
    void show()
    {
        std::cout << "show() is called" << std::endl;
        showmsg();
    }
    CPerson(int age = 4, std::string name = "tiger") :age{age},name{name}
    {
        std::cout <<  "Constructor called "<< std::endl;
    }
};

int main()
{
    CPerson person1;
    //person1.showmsg();    //私有成员不能被访问
    person1.show();
    //std::cout << person1.age << std::endl;  //私有成员不能被访问
    std::cout << person1.getAge() << std::endl;
}

类的友元函数

友元函数:不是类的成员的函数能够访问类的所有成员。

使用关键字friend来定义,可以在定义中添加友元函数的原型,也可以添加整个函数定义。

在类定义内定义的友元函数默认也是内联函数。

友元函数声明放在类的内部,友元函数的定义放在类外部。

#include <iostream>
#include <iomanip>
#include <string>

class CPerson
{
//private: 可以省略
    std::string name;
    int age;
    friend void show(CPerson cPerson);   //类内友元函数声明
public: 
    CPerson(int age = 4, std::string name = "tiger") :age{age},name{name}
    {
        std::cout <<  "Constructor called "<< std::endl;
    }
};
//类外友元函数定义
void show(CPerson cPerson)
{
    std::cout << cPerson.name << "'age is " << cPerson.age << std::endl;
}

int main()
{
    CPerson person1;
    show(person1);
}

将友元函数定义放在类的内部,这样影响可读性,虽然仍然是全局作用域。

#include <iostream>
#include <iomanip>
#include <string>

class CPerson
{
//private: 可以省略
    std::string name;
    int age;
    friend void show(CPerson cPerson)//友元函数声明和定义
    {
        std::cout << cPerson.name << "'age is " << cPerson.age << std::endl;
    }  
public: 
    CPerson(int age = 4, std::string name = "tiger") :age{age},name{name}
    {
        std::cout <<  "Constructor called "<< std::endl;
    }
};

int main()
{
    CPerson person1;
    show(person1);
}

默认复制构造函数

编译器生成默认的复制构造函数。

复制构造函数通过同类的现有对象进行初始化来创建类对象。

复制构造函数的默认版本通过逐个成员复制现有对象来创建新对象。

如果拥有指针成员的类,默认复制构造函数将不能正常工作。这种情况下,必须创建自己的复制构造函数。

#include <iostream>
#include <iomanip>
#include <string>

class CPerson
{
//private: 可以省略
    std::string name;
    int age;
    friend void show(CPerson cPerson)//友元函数声明和定义
    {
        std::cout << cPerson.name << "'age is " << cPerson.age << std::endl;
    }  
public: 
    CPerson(int age = 4, std::string name = "tiger") :age{age},name{name}
    {
        std::cout <<  "Constructor called "<< std::endl;
    }
};

int main()
{
    CPerson person1(2,"copy");
    CPerson person2(person1);        //调用默认复制构造函数
    show(person2);
}

this指针

任何成员函数执行时,都自动包含一个名为this的隐藏指针,它指向调用该函数时使用的对象。

如果需要,也可以在成员函数中显式地使用this指针。

#include <iostream>
#include <iomanip>
#include <string>

class CPerson
{
//private: 可以省略
    std::string name;
    int age;
    friend void show(CPerson cPerson)//友元函数声明和定义
    {
        std::cout << cPerson.name << "'age is " << cPerson.age << std::endl;
    }  
public: 
    CPerson(int age = 4, std::string name = "tiger") :age{age},name{name}
    {
        std::cout <<  "Constructor called "<< std::endl;
    }
    void setAge(int age)
    {
        this->age = age;
    }
};

int main()
{
    CPerson person1(2,"copy");
    CPerson person2(person1);
    show(person2);
    person2.setAge(40);
    show(person2);
}

类的const对象

如果将某个类对象声明为const,则编译器将不允许该对象调用任何可能修改它的成员函数。

声明为const的对象,其this指针也是const,因此编译器不允许调用没有将传递给它的this指针指定为const的成员函数。

类的const成员函数

为了使成员函数中的this指针称为const,必须在类定义内将该函数声明为const。

只能对类成员函数这么做,对普通全局函数不能这么做。

function_type function_name(parameter_list) const    //必须在类内部的函数
{
}

类外部的成员函数定义

当const成员函数的定义出现在类外部时,函数头必须添加关键字const。

class class_name
{
    function_type function_name(parameter_list) const;    //类内部
}

function_type function_name(parameter_list) const
{

}

类对象的数组

可创建类对象的数组。

class class_name
{
    
}

class_name variable[count];    //类对象的数组

类的静态成员

类的静态数据成员

将类的某个数据成员声明为static时,只能定义一次该静态数据成员,而且要被同类的所有对象共享。

每个静态数据成员只有一个实例存在,与定义了多少类对象无关。

 在类定义外部初始化静态数据成员的初始化,初始化语句中没有使用static关键字,需要使用类名和作用域解析运算符来限定成员名。

class class_name
{
    static variable_type  static_variable;    //类内定义
}

variable_type class_name::static_variable{}; //类外初始化

类的静态函数成员

通过将某个函数成员声明为static可以使该函数独立于本类的任何具体对象。

它们没有this指针。

static函数的优点:即使本类的任何对象都不存在,它们也能存在并被调用。此时,静态函数成员只能使用静态数据成员(这时就有静态数据成员存在)。

class class_name
{
    static function_type  static_function(parameter_list)
    {

    };    //类内定义
}

class_name::static_function(parameter_list); //类外通过类名调用

class_name class_name_example;
class_name_example.static_function(parameter_list); //类外实例调用

类对象的指针和引用

类对象可能涉及相当多的数据,因此对对象使用按值传递机制非常耗时和低效,因为需要赋值每一个实参对象。

使用引用形参可以避免这个系统开销,而且引用形参对于一些类的操作是必不可少的。

类对象的指针

能以声明其他指针的相同方式,声明指向类的指针。

class class_name
{
}

class_name* ptr{};//类的指针
class_name class_name_example;
ptr = &class_name_example;

类对象的引用

声明和使用类对象的引用与声明,和使用基本类型变量的引用之间,实质上没任何区别。

引用是已存在变量的别名,而指针是存储变量地址的变量。

①C++中的引用本质上是 一种被限制的指针

②由于引用是被限制的指针,所以引用是占据内存的。

③在使用高级语言的层面上,是没有提供访问引用的方法的。并且引用创建时必需初始化,创建后还不能修改。

实现复制构造函数

复制构造函数是用同类的现有对象进行初始化,从而创建新对象的构造函数,因此需要接受同类的对象作为实参。

编译器为了处理复制构造函数的这条调用语句,需要调用复制构造函数来创建实参的副本。但是,由于按值传递,第二次调用同样需要创建实参的副本,因此还得调用复制构造函数,就这样持续不休。

解决方法是使用const引用形参。

 如果函数的形参是引用,则调用该函数时不需要复制实参。函数直接访问被调用函数中的实参变量。const限定符用来确保该函数不能修改实参。

#include <iostream>
#include <iomanip>
#include <string>

class CPerson
{
    //private: 可以省略
    std::string name;
    int age;

public:
    CPerson(int age = 4, std::string name = "tiger") :age{ age }, name{ name }
    {
        std::cout << "Constructor called " << std::endl;
    }
    CPerson(const CPerson& cPerson)   //复制构造函数
    {
        this->age = cPerson.age;
        this->name = cPerson.name;
        std::cout << "Copy Constructor called " << std::endl;
    }
};

int main()
{
    CPerson person1(2, "copy");
    CPerson person2(person1);//复制构造函数
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值