// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <vector>
#include <string>
using namespace std;
/*
友元不具有传递性,B为A的友元,C为B的友元 , B可以访问A的私有,但是C不可以访问A的私有
*/
class Screen
{
private:
typedef string::size_type pos;
pos cursor = 0;//光标
pos height = 0, width = 0; //位置
string contents; //内容
mutable size_t access_ctr; //可变数据成员 即使是const;
void do_display(ostream& os)const {//重载const
os << contents;
}
public:
Screen() = default; //构造
Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht * wd, c) {} //构造
char get() const {
return contents[cursor];
}
void some_member() const;
Screen& move(pos r, pos c);//隐式内联
inline char get(pos ht, pos wd) const;//显式内联
Screen& set(char); //设置光标所处位置的字符
Screen& set(pos, pos, char);//设置任意位置的字符
Screen& display(ostream& os) {
do_display(os); return *this;
}
const Screen& display(ostream& os)const
{
do_display(os);
return *this;
}
friend class Window_mgr;//Window_mgr类的成员可以访问Screen的私有部分 , 类友元
friend void Window_mgr::clear(ScreenIndex);//函数友元 该函数可以获得Screen的私有部分
};
class Window_mgr
{
private:
vector<Screen> screens{ Screen(24,80,' ') };
public:
using ScreenIndex = vector<Screen>::size_type;
void clear(ScreenIndex);
};
/*----> Screen类成员实现 */
inline Screen& Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
inline void Screen::some_member() const
{
++access_ctr;
}
inline Screen &Screen::set(char c)
{
contents[cursor] = c;
return *this;
}
inline Screen& Screen::set(pos r, pos col, char ch)
{
contents[r * width + col] = ch;
return *this;
}
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
/* Screen类成员实现 <----- */
/*----> Window_mgr类成员实现 */
inline void Window_mgr::clear(ScreenIndex i)
{
Screen& s = screens[i]; //s是一个Screen的引用, 指向想要清空的屏幕
s.contents = string(s.height + s.width, ' '); //重置为空白
}
/* Window_mgr类成员实现 <----- */
int main()
{
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
7.5.5聚合类
聚合类可以使得用户直接访问其成员,并且具有特殊的初始化语法形式。
所有成员都是public的
没有定义任何构造函数
没有类内初始值
没有基类,没有virtual函数
#include <iostream>
#include <string>
using namespace std;
struct Data //聚合类
{
int ival;
string s;
};
int main()
{
Data val1 = { 10,"Anna" }; //初始化聚合类成员
cout<<val1.ival<<" "<<val1.s<<endl;
return 0;
}
7.5.6 字面值常量constexpr
constexpr的参数和返回值必须是字面值类型;(字面值类型:算数类型,引用,指针,某些类等);
数据成员都必须是字面值类型;
类必须至少含有一个constexpr构造函数;
如果一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式;或者如果成员的初始值属于某种类型,则初始值必须使用成员自己的constexpr构造函数;
类必须使用构造函数的默认定义,该成员负责销毁对象。
7.6类的静态成员static
通过在成员的声明之前加上关键字static使得其与类关联在一起。
类的静态成员存在于任何对象之外,对象中不包括任何与静态数据成员有关的数据。
静态成员函数不与任何对象绑定在一起,不包括this指针。
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class Account
{
public:
void calculate() {
amount += amount * interestRate;
}
static double rate() { return interestRate;}
static void rate(double);
private:
string owner;
double amount;
static double interestRate;//静态
static double initRate();//静态
};
void Account::rate(double newRate)
{
interestRate = newRate;
}
int main()
{
double r;
Account ac1;
Account* ac2 = &ac1;
r = ac1.rate();
r = ac2->rate();
}
术语表
类:C++提供的自定义数据类型的机制,类可以包括数据,函数和类型成员,一个类定义一种新的类型和一个新的作用域;
构造函数:用于初始化对象的一种特殊的成员函数;
封装:分离类的实现和结构,从而隐藏了类的实现细节;在C++语言中,通过把实现部分设置为private完成封装的任务;
友元:类向外部提供其非公有成员访问的一种机制,友元的访问权限与成员函数一样,友元可以是类,也可以是函数;
接口:类提供的操作;通常不含有数据成员;