The fundamental ideas behind classes are data abstraction and encapsulation.

Data abstraction is a programming technical that relies on the separation of interface(declaration) and implementation(definition)

A class designer desings and implements a class for users of that class.

In this class, the user is a progrmmer, not the utilmate user of the application.

Every member must be declared inside its class, and we can difine a member's body either inside or outside of the class body.

Objects that are const, and references or pointers to const objects may call only const member functions.

The compiler process class in two steps

  • the member declarations are compiled first
  • the member function bodies are processed.

The name of a member defined outside the class must inlucde the class name.

class Sales_data::arg_print() const{
if (units_sold){
return revenue / units_sold;
} else {
return ;
}
}

Define a funcion to return "this" object

Sales_data & Sales_data::combine(const Sales_data & rhs){
units_sold += rhs.units_sold;
return *this; // return current object
}

To return an lvalue, our combine function must return a reference.

Member functions that are part of the interface of a class should be declared in the same header as the class itself.

istream & read(istream & is, Sales_data & item){
is >> itme.bookNo >> item.units_sold;
return is;
}
ostream & print(ostream & os, const Sales_data & item){
os << item.isBN();
return os;
}

Both read an writer take a reference to thier respective IO class types. The IO class cannot be copied, so only passed by reference.

Reading or Writing to a stream changes that stream, so both functions take ordinary reference, not references to const.

Sales_data add(const Sales_data & lhs, const Sales_data & rhs){
Sales_data sum = lhs; // copy data members from lhs into sum. statement[1]
sum.combine(rhs);
return sum;

We initialize sum as a copy of lhs. By default, copying a class object copies that object's members.

In Java, statement[1] only assign the reference of lhs to sum. Both sum and lhs points to the same object in heap storage.

In C++, statement[1] copy the all member from lhs to sum. lhs and sum points to different object, and are independent.

The compiler generate a default constructor automatically only if a class declare no constructors.

Many class that need dynamic memory can (and generally should) use a vector or a string to manage the necessary storage. Classes that use vectors and string avoid the complexites of allocating and deallocating memory.

A class may contain zero or more access specifier(e.g. private, public). Each access specifier specify the access level of the succeeding members. The specified access level remain in effect until the next access specifier or the end of the class body.

The only difference between struct and class is the default access level.

  • In struct, the members defined before the first accesss specifier are public.
  • In class, these members are private.

Friend

A class can allow class or function to access its non-public members by marking that as a frined.

class Sales_data{
friend Sales_data add(const sales_data&, const Sales_data&);
public:
Sales_data() default;
private:
string bookNo;
}; // declarations for members which are part of the Sales_data interface
Sales_data add(const Sales_data&, const Sales.data &);

It is good idea to group friend declaration together at the beginning or end of the class. To make a friend visible to the users of the class, we usually declare each friend(outside the class) in the same header as the class.

Encapsulation provide two important advantage:

  • User code cannot corrupt the state of an encapsulated object
  • The implementation of an encapsulated class can change over time without requiring changes in user-level code.

Although user code need not change when a class definition changes, the source files that use a class must be re-compiled if the class changes.

Class often have small functions that can benefit from being inline.

Mutable

A mutable data member are never const, even when it is a member of a const class

class Screen{
public:
void some_member() const;
private:
mutable size_t access_ctr; // may change even in a const object
}; void Screen::some_member() const{
access_ctr++;
};

In-class initializer

When we provide an in-class initializer, we must do so following on = asign or inside braces.

class windows_mgr{
private:
// By default, a windows_mgr has one blank screen
std::vector<Screen> screens{screen(, , ' ')};
}

Return *this

class Screen{
public:
Screen& set(char);
Screen& move(int i, int j);
// other members. e.g. cursor
}; inline Screen& Screen::move(int i, int j){
cursor = i * width + j;
return *this; // return this object as lvalue
}
inline Screen& Screen::set(char c){
contents[cursor] = c;
return *this;
}

If we concatenate a sequence of these actions into a single expression

    myScreen.move(, ).set('#');

Above single expression is equal to

    myScreen.move(, );
myScreen.set('#');

Had we defined move and set to return Screen, rather thane Screen &. This statement will be vary different.

    Screen tmp = myScreen.move(, );    // the return value would be copied
tmp.set('#'); // the content inside myScreen will be unchanged.

A class is not defined until its class body is completed. A class cannot have data members of its own type.

However, a class is considered declared(not yet defined) as soon as its calss name has been seen. Therefore, a class can have data members that are pointers or reference to its own type.

class Link_Sales{
Screen window;
Link_Sales *next;
Link_Sales *prev;
};
class Screen{
// Windows_mgr can access the non-public part of class Screen.
friend class Windows_mgr;
} void Windows_mgr::clear(int i){
Screen & s = screens[i];
s.content = '';
}

It is important to understand that friendship is not transitive. If class Windows_mgr has its own friends, that friends have no special access to Screen.

Each class controls which class or function are its friends.

Although overload functions share a common name, they are still different functions. Therefore a class must define as a friend each function in a set of overload functions that it wish to mark as friend.

The lookup rules for friends

Struct X{
friend void f();
X() { f(); } // error: no declaration for f()
void g();
void h();
} void X::g() { return f(); } // error: f has not been declared
void f(); // declares the function defined in X()
void X:h() { return f(); } // ok

Remember, some compiler do not enforce the lookup rules for friends.

class Window_mgr{
public:
screenIndex addScreen( const Screen&);
// other members
}; // return type is seen before the scope of Window_mgr
Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen & s){
screens.push_back(s);
return screens.size() - ;

To use screenIndex for the return type, we must specified.

Member function definitions are processed after all of the declaration in class are processed by compiler. So member functions can use any member declared inside the calss

Even though the class member(height) is hidden, it is accessable by qualified the member's name with the class's name or with this pointer expectly

void Screen::dummy_fcn(pos height){
cursor = width * this->height;
// alternative way
cursor = width * Screen::height;
}

The global object is accessable by the scope opertion.

void Screen::dummy_fcn(pos height){
cursor = width * ::height; // the global height
}

Reference:

C++ Primer, Fifth Edition, chapter 7 Classes

随机推荐

  1. Swift_下标

    Swift_下标 点击查看源码 func testSubscripts() { //下标关键字subscript //array测试 struct TestArray { //内部数组 var arr ...

  2. jQuery 属性操作 - addClass() 和 removeClass() 方法

    实例 向第一个 p 元素添加一个类: $("button").click(function(){ $("p:first").addClass("int ...

  3. angular.js-1初识

    初识AngularJS AngularJS 为了克服HTML在构建页面上的不足,通过新的属性和表达式扩展了 HTML(AngularJS 通过指令扩展了 HTML,且通过表达式绑定数据到 HTML). ...

  4. linux操作之ntsysv

    命令nysysv , 提示Command nod found  先在命令行输入 export PATH=/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11R6/bin:    ...

  5. php ecshop 二级域名切换跳转时session不同步,解决session无法共享同步导致无法登陆或者无法退出的问题

    echshop基础上做了单点登录的 一级域名与二级域名 退出时 清空session 都是一级域名的session 因为二级域名的session是设置在二级域名上的 echshop基础上没有做单点登录的 ...

  6. 面试:Hbase和Hive的区别

    区别: 1. Hive是一个构建在Hadoop基础设施之上的数据仓库,通过HQL查询存放在HDFS上的数据,不能交互查询.HBase是一种Key/Value系统,它运行在HDFS之上,可以交互查询. ...

  7. Python学习:11.Python装饰器讲解(二)

    回顾 上一节我们进行了Python简单装饰器的讲解,但是python的装饰器还有一部分高级的使用方式,这一节就针对python装饰器高级部分进行讲解. 为一个函数添加多个装饰器 今天,老板又交给你一个 ...

  8. rubymine自动转义双引号

    如果你使用rubymine在编写JSON字符串的时候,然后要一个一个\去转义双引号的话,就实在太不应该了,又烦又容易出错.在rubymine可以使用Inject language帮我们自动转义双引号 ...

  9. ecshop跨站漏洞详情及修补网站漏洞

    ecshop目前最新版本为4.0,是国内开源的一套商城系统,很多外贸公司,以及电商平台都在使用,正因为使用的人数较多,很多攻击者都在挖掘该网站的漏洞,就在最近ecshop被爆出高危漏洞,该漏洞利用跨站 ...

  10. Java多线程一些基础知识

    最近复习了一些多线程方面的基础知识,做一下总结,多以自己的理解来文字叙述,如果有漏点或者理解错的地方,欢迎各位大佬多多指出: ps:线程分为用户线程和守护线程,当程序中的所有的用户线程都执行完了之后, ...