C++ 坑了我不少的时间, 这回把类算是弄得明白一些, 在此记录一下内容非常繁杂, 请做好心理准备
我会以代码的形式来表达, 并且附上一些解释
编译器分两步处理类:
编译成员的声明
直到类全部可见后才编译成员函数体
C++ 中 class 与 struct 的区别?
C++ 中唯一区别就是默认的访问权限, struct 是 public,class 是 private
C# 中区别很大, 详情百度
.h 文件 (注意: 是 struct)
- struct Sales_data {
- // 定义友元函数让其可以访问类的非公有成员
- friend Sales_data add(const Sales_data & , const Sales_data & );
- public:
- // Sales_data() = default;
- // 构造函数, 不能声明 const
- // 等同于编译器自动合成的构造函数
- // 在 (= default) 在类的内部, 则默认构造函数是内联的, 如在类的外部, 则该成员默认不是内联的
- Sales_data() : Sales_data("", 0, 0) {}
- // 委托构造函数: 使用它所属的类的其他构造函数执行自己的初始化过程
- /* explicit 抑制构造函数的隐式转换, 只允许出现的类内 */
- Sales_data(const string & s) : bookNo(s) {}
- Sales_data(const string & s, unsigned n, double p) : bookNo(s),
- units_sold(n),
- revenue(p * n) {}
- string isbn() const {
- return bookNo;
- }
- // 等价于
- // string isbn(const Sales_data *const this// 隐式 //) {return this->bookNo;}
- // 意思就是 this 是一个指向常量的常量指针不能修改 this 中的内容
- Sales_data & combine(const Sales_data & );
- private: double avg_price() const;
- string bookNo;
- unsigned units_sold = 0;
- double revenue = 0.0;
- };
.cpp 文件
- Sales_data& Sales_data::combine(const Sales_data &rhs)
- {
- units_sold += this->units_sold;
- revenue += rhs.revenue;
- return *this; // 返回指针引用
- }
- double Sales_data::avg_price() const
- {
- if (units_sold)
- return revenue / units_sold;
- else
- return 0;
- }
- Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
- {
- Sales_data sum = lhs;
- sum.combine(rhs);
- return sum;
- }
main 函数
- int main() {
- Sales_data total;
- total.isbn();
- // 等价于
- // total.isbn(&total);
- // 调用时候传入了 total 对象的地址
- const Sales_data sales_data;
- // 直到构造函数完成初始化过程, 对象才能真正取得其常量属性
- // 构造函数在 const 对象的构造过程中可以向其写值
- total.combine(sales_data).isbn();
- // 非引用传参调用拷贝构造(此函数是引用参数, 则没有拷贝构造)
- // 返回一个类对象调用拷贝构造
- total = sales_data;
- // 赋值操作
- Sales_data obj(); // 声明了一个函数
- Sales_data obj2; // 声明了一个对象
- Sales_data item;
- string null_book = "9-999-99999-9";
- item.combine(null_book); // 将 null-book 隐式转换成 Sales_data 对象
- //item.combine("9-999-99999-9"); // 错误, 只允许一步转换, 不能将字符转换成 string 再转换成对象
- // this 是一个常量指针
- return 0;
- }
class Screen 与的类示例友元类
- class Screen {
- public: typedef std: :string: :size_type pos;
- // 等同于
- // using pos = std::string::size_type;
- // 必须先定义后使用
- friend class Window_mgr;
- // Window_mgr 的成员可以访问 Screen 类的私有成员
- // friend void Window_mgr::clear(ScreenIndex);
- // 让函数作为友元
- Screen() =
- default;
- Screen(pos ht, pos wd, char c) : height(ht),
- width(wd),
- contents(ht * wd, c) {}
- char get() const // 隐式内联
- {
- return contents[cursor];
- }
- inline char get(pos ht, pos wd) const; // 显式内联
- Screen & move(pos r, pos c); // 可以在类的外部声明时定义成内联函数
- Screen & set(char);
- Screen & set(pos, pos, char);
- const Screen & display() const;
- void dummy_fcn(pos height) {
- cursor = width * height; // 用的是参数 height
- cursor = width * this - >height; // 用的是成员 height
- // cursor = width * ::height; // 用的是全局的 height
- }
- private: pos cursor = 0;
- pos height = 0,
- width = 0;
- std: :string contents;
- mutable size_t access_ctr = 0; // mutable(可变数据成员), 在 const 成员函数中也可以改变值
- };
- char Screen: :get(pos ht, pos wd) const {
- pos row = ht * width; ++access_ctr; // 正确
- // ++cursor; 错误
- return contents[row + wd];
- }
- inline Screen & Screen: :move(pos r, pos c) // 声明的时候声明 inline 函数
- {
- pos row = r * width;
- cursor = row + c;
- return * this;
- }
- inline Screen & Screen: :set(char c) {
- contents[cursor] = c;
- return * this;
- // 返回对象的引用, 说明返回的是对象本身, 而不是对象的拷贝
- // 如果返回类型为 Screen, 则返回的是对象的拷贝
- }
- inline Screen & Screen: :set(pos r, pos col, char ch) {
- contents[r * width + col] = ch;
- return * this;
- }
- inline const Screen & Screen: :display() const {
- return * this; // const 成员函数返回其指针, 则为常量指针
- } class Window_mgr class Window_mgr {
- public: using ScreenIndex = std: :vector < Screen > ::size_type;
- void Clear(ScreenIndex);
- ScreenIndex addScreen(const Screen & );
- private: std: :vector < Screen > screens {
- Screen(24, 80, )
- };
- // 类内初始值, 必须以符号 = 或 {} 表示
- };
- void Window_mgr: :Clear(ScreenIndex index) // void 为作用域之外, 从 Window_mgr 开始为作用域内
- {
- Screen & s = screens[index];
- s.contents = std: :string(s.height * s.width, );
- // 因 Window_mgr 是 Screen 的友元类, 所以可以访问 Screen 的私有成员 heightwidth 和 contents
- // 注: 友元关系不存在传递性, 如果 Window_mgr 有友元类, 其友元类没有访问 Screen 的权利
- }
- Window_mgr: :ScreenIndex Window_mgr: :addScreen(const Screen & s) // 返回类型在类作用域中定义, 则必须用类名
- {
- screens.push_back(s);
- return screens.size() - 1;
- }
来源: http://www.bubuko.com/infodetail-2498188.html