c++类的特性探究(一)

原创 2015年10月04日 18:24:16

类的定义可以使用struct关键字或者class关键字,两者唯一的区别就是默认的访问权限。访问权限与类的访问控制说明符有关:

public:定义在public后面的成员可以在整个程序里面被访问

private:定义在private后面的成员只能在类内部被访问

struct Sales_data{
public:

//public成员,可在整个程序里面被访问
    //构造函数,用于创建对象时初始化数据成员
    Sales_data()=default;
    Sales_data(const string &s,unsigned n,double p):bookNo(s),units_sold(n),revenue(p*n){}
    Sales_data(const string &s):bookNo(s){}
    Sales_data(istream&);
    //成员函数:关于sales_data对象的操作
    string isbn() const {return bookNo;}
    Sales_data & combine(const Sales_data&);
private:

//private成员,仅可在类内部被访问
    double avg_price()const{return units_sold?revenue/units_sold:0;};
    //数据成员:属于sales_data对象的属性
    string bookNo;
    unsigned units_sold=0;
    double revenue=0.0;
};

注:有些类成员可能定义在第一个说明符之外,那么此时如果使用struct关键字定义类,这些成员是public的,如果使用class关键字定义类,这些成员是private的。


友元:为了使得类的非成员接口函数能够访问类中的成员(包括公有私有),c++中引入友元一词,用以表示可以访问类的私有成员的友情函数。友元声明只能再类的内部,一般在顶部或者尾部,在函数前面加上friend关键字:

struct Sales_data{
friend Sales_data add(const Sales_data&,const Sales_data&);
friend ostream &print(ostream&,const Sales_data);
friend istream & read(istream&,Sales_data&);

public:
    //构造函数,用于创建对象时初始化数据成员
    Sales_data()=default;
    Sales_data(const string &s,unsigned n,double p):bookNo(s),units_sold(n),revenue(p*n){}
    Sales_data(const string &s):bookNo(s){}
    Sales_data(istream&);


    //成员函数:关于sales_data对象的操作
    string isbn() const {return bookNo;}
    Sales_data & combine(const Sales_data&);
private:
    double avg_price()const{return units_sold?revenue/units_sold:0;};
    //数据成员:属于sales_data对象的属性
    string bookNo;
    unsigned units_sold=0;
    double revenue=0.0;
};

//这三个即为友元
Sales_data add(const Sales_data&,const Sales_data&);
ostream &print(ostream&,const Sales_data);
istream & read(istream&,Sales_data&);

友元函数虽然已经在类内部有过一次声明,但是在类的外部还需一次声明,通常将类的声明和友元函数的声明放在同一个头文件。

友元函数也可以直接在类内部定义,但是还是需要在类的外部再次进行声明以使得友元函数可见。

除了可以声明友元函数外,还可以声明友元类以及某一个类中的部分成员函数为友元函数。

class screen{

friend class WindowMgr;//声明class WindowMgr是class screen的友元类,class WindowMgr的成员函数可以访问class screen的非公有成员

friend void window_mgr::clear(int);//声明window_mgr的成员函数clear为screen的友元函数,可以访问screen的非公有成员。

}

如果要将某个类的成员函数作为一个类的友元,我们需要严格的组织程序结构,以window_mg的clear函数作为screen的友元为例:

1.首先定义window_mgr类,其中声明clear函数,但是不能定义它,因为它将要用到的screen还没有声明。

2.定义screen类,包括对于window_mgr的clear函数的友元声明

3.定义clear函数,此时可以使用screen。



友情小贴士:封装的益处

1.确保用户代码不会无意间破坏封装对象的状态

2.类的具体实现细节可以随时改变,而不用调整用户级代码


类的可变数据成员:

有时候我们希望只改变对象的某一个数据成员(即便这个对象是const对象),此时可以在数据成员的声明里面加入关键字mutable。

class Screen{
public:
    void some_member()const;//改变可变数据成员access_ctr,统计成员函数被访问次数
private:
    mutable size_t access_ctr=0;//可变数据成员
};
void Screen::some_member()const{
    ++access_ctr;
}


关于返回*this的成员函数

有些成员函数需要返回调用对象以进行下一步操作,此时成员函数应该返回对于调用对象的引用,这样才可保证所有的操作都是作用在调用对象上面。例如:

myScreen.move(4,0).set('#');//移动光标同时设定光标显示的字符

此时如果move函数返回对象的引用,那么紧随其后的set函数也是作用在myScreen上面;如果move函数返回对象,那么set函数将会作用在所返回的对象副本上,与myScreen无关。对于返回常量非常量引用可以使用函数重载的方法解决。对于函数体中对于常量对象和非常亮对象不同的操作可以将不同功能的代码独立成一个成员函数,由于类中的成员函数都是内联函数,所以不会带来函数调用的额外开销。


类的作用域:

当我们要使用类中的成员时,我们必须在这之前使用类名和作用运算符指定具体的类。在类的外部定义成员函数时,一般函数名前面会有类名,因此函数体和参数列表都可以使用类的成员,但是函数的返回类型是在函数名之前的,如果函数返回值类型需要用到类中的成员,那么必须也要使用作用域运算符指定具体的类,即便使用的是同一个类。

编译器处理类定义的两个阶段:

1.首先编译全体成员的声明(包括成员函数)

2.直到类全部可见之后才编译函数体(函数声明中返回类型、参数列表所用到的名字必须在声明以前已经出现过)

成员函数的块中使用符号时的名字查找规则:

1.首先在函数内部查找该名字

2.如果函数内部没有其定义或者声明,那么在类中查找该名字(成员函数之前或者之后出现的都可以,只要在类中声明)

3.如果在类中仍然未找到该名字,那么在类外的全局作用域中寻找该名字(必须在使用该名字之前有过定义)

注:类型别名比较特殊,类的内部不允许覆盖外部的类型别名。并且即便是在类内部,定义类型别名也必须先定义后使用

综合上述规则可理清楚程序中有关符号作用域的问题

相关文章推荐

C++新特性(类与对象的各种指针和引用)

对象与函数的关系(知道如何把对象指针和引用作为函数参数)   将对象指针作为函数的参数,传递给函数处理有两个好处 1、减少数据分配的时间和空间,提高了程序运行的效率; 2、在被调函数中,可以直...

C++类的继承特性

整个c++程序设计全面围绕面向对象的方式进行,类的继承特性是c++的一个非常非常重要的机制,继承特性可以使一个新类获得其父类的操作和数据结构,程序员只需在新类中增加原有类中没有的成分。下面我们简单的来...

C++不同继承方式的基类和派生类特性

几个注意点:        1. 无论以什么方式被继承,派生类依然是无法访问基类的私有成员的。        2. 在私有继承里,派生类是以私有的方式继承基类的共有成员和保护成员,即它们的共有成员...
  • BelugaW
  • BelugaW
  • 2015年10月29日 15:35
  • 331

《C++高级编程》--改变类覆盖方法的特性

1、改变覆盖方法的返回类型:协变返回类型covariant returns type 一般情况下,子类覆盖父类的方法时,是不允许修改函数返回类型的。 CODE 1 class Foo { p...

Python中C++类特性的实现原理

#python类的特性#而且python还可以实现函数的重载,通过不同的参数来做不同的内部实现#def overload(*args):# def overload1():# print("No a...

c++类的特性之继承

继承: c++类的三大特性,封装,继承,多态。继承的作用是代码的复用和多态的实现。类的继承,是新的类从已有类那里得到已有的特性,并且有自己的的特性,从已有类产生新类的过程就是类的派生。原...

C++ 新特性 关于类1

1.使用=default生成默认构造函数 在C++11新标准中,如果我们需要默认的行为,那么可以通过在参数列表后面写上=default来要求编译器生成构造函数。其中,=default既可以和声明一起...

C++类特性:this指针与函数的全局性(一)

我们通过一个例子来切入本文的主题: #include using namespace std; class test1 { public: test1(int data) { this->...

【足迹C++ primer】17、类的其他特性(2)

类的其他特性(2) 返回*this的成员函数 返回*this的成员函数,则调用的直接就是类的对象本身,而不是他的副本。 #include #include using namespace ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c++类的特性探究(一)
举报原因:
原因补充:

(最多只允许输入30个字)