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.封装 突破了C语言函数的概念,封装可以隐藏实现细节,使得代码模块化。2.继承 继承可以扩展已存在的代码模块(类);达到代码重用的目的。要实现继承,可以通过“继承”(Inheri...
  • michael019
  • michael019
  • 2015年10月01日 10:03
  • 1861

PYTHON-函数特性

函数:在Python中,定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。 递归函数,自身调用自身就是递...
  • u010008539
  • u010008539
  • 2015年04月13日 17:27
  • 540

理解C++三大特性

封装,继承,多态      封装可以隐藏实现细节,使得代码模块化,继承可以扩展已存在的模块,它们目的都是为了:代码重用。而多态是为了实现另一个目的:接口重用。 什么是多态?   ...
  • Doo66
  • Doo66
  • 2016年08月15日 10:26
  • 4963

C++类的继承特性

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

C++面向对象程序设计——类和对象(个人整理)

对象: object 客观世界中任何一个事物都可以看成一个对象,如自然物体(汽车,房子,班级...) 可以看到一个班级作为一个对象有两个要素: 1、班级所属系和专业,人数等静态特征(属性); ...
  • qq_26816417
  • qq_26816417
  • 2017年03月13日 00:37
  • 289

C++:C++11新特性详解(1)

前言:虽然目前没有编译器能够完全实现C++11,但这并不意味着我们不需要了解,学习它。深入学习C++11,你会发现这根本就是一门新的语言,它解决了c++98中许多遗留下来的问题。早晚会有一天,C++1...
  • linwh8
  • linwh8
  • 2016年06月05日 23:28
  • 5223

每个C++开发者都应该使用的十个C++11特性

这篇文章讨论了一系列所有开发者都应该学习和使用的C++11特性,在新的C++标准中,语言和标准库都加入了很多新属性,这篇文章只会介绍一些皮毛,然而,我相信有一些特征用法应该会成为C++开发者的日常用法...
  • caoshangpa
  • caoshangpa
  • 2016年04月06日 15:32
  • 1431

C++学习之引用特性

引用即给变量赋予一个别名,就像外号一样,我叫李晓明,外号小明,实际都是指李晓明这个人。 #include using namespace std; int main() { //C++中的引用 ...
  • u011707827
  • u011707827
  • 2016年03月05日 17:56
  • 336

C++14新特性总结

C++14这一继C++11之后的新的C++标准已经被正式批准,正在向ISO提交,将于年内发布。C++之父Bjarne Stroustrup说道,尽管与C++11相比,C++14的改进“有意做的比较...
  • weiqubo
  • weiqubo
  • 2016年09月06日 22:34
  • 13205

C++的高级特性

本文介绍以下内容:如何创建动态数组,如何使用向量,如何使用迭代器,define如何定义函数,函数如何返回复杂类型,STL中的快速排序。 动态数组 int n; n=10;//此处可以把用户从界面上输入...
  • qq_35488967
  • qq_35488967
  • 2017年02月25日 19:08
  • 475
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c++类的特性探究(一)
举报原因:
原因补充:

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