c++Primer第七章:类

代码

建议

1.返回已经存在的数据,尽量用引用类型,减少拷贝。

2.函数前const表示返回的是常量,后const表示不会对类中方数据进行改变,当作只读函数就行。

3.函数传参的时候尽量传引用,如果没有对数据进行修改,就加个const。

4.this指向当前对象,有时候为了连续调用即点连点会使用,具体看基础类学习。

5.使用IO类为参数,由于IO类型不可拷贝,所以使用的是引用参数,返回的也是引用类型,保证输出的流对象是一个对象,即传进来是谁,返回的也是谁c++p270

5.运算符重载问题,使用了IO流的都是IO类调用本类的数据或者函数,所以必须是友元函数,否则没有权限。

6.有其他构造函数了也要写默认构造函数,复合类或者嵌套类有时候编译器不能自动合成默认构造函数。

7.const成员函数可以改变mutable数据成员。

8.const对象只能调用const成员,但是const对象的数据不能改变,所以使用前后两个const进行函数重载。

9.委托构造函数,可以根据输入的不同调用不同的构造函数。

10.explicit防止构造函数的隐式转换,例如只给某成员函数传入string,函数参数类型是class,结果自动调用了相应的构造函数,将类型进行了转换。explicit函数只能直接初始化。

问题以及学习内容

1.类名和define 重名

在这里插入图片描述
友元,相当于谁被用,谁写friend

2.友元类分两个文件写

class A 是 class B 的友元类,即class A可以使用class B 中数据
在 A.h 中,先声明class B,

class B;
class A{
	private:...
	public:...
}

在B.h中

#include"A.h"
class B{
	private:...
	public:
	friend class A
	...
}

3.友元函数-非成员函数

class A{
	public:
	friend void show(A &)private:
}
void show(A &a){
...
}

4.友元函数-成员函数

class A
该类中使用class B的数据

class B
class A{
	public:
	void show(B &);
	private: 
}

class B

class B{
	public:
	friend void A::show(B &);
}
void A::show(B &){};

代码内容

1.友元类

class A.h

#ifndef WINDOW_MGR
#define WINDOW_MGR
#include<iostream>
#include<vector>
//友元类
#include"Screen.h"
using namespace std;
class Screen;
class Window_mgr
{
private:
    //默认情况下,一个Window_mgr包含一个全是‘*’的Screen
    vector<Screen> screens{Screen(5,5,'*')};
public:
    typedef vector<Screen>::size_type ScreenIndex;
    //指定编号的Screen清空
    void clear(ScreenIndex); 
    //输出屏幕
    void show();
    //增加屏幕
    ScreenIndex addScreen(const Screen&);
};

#endif

class A.cpp

#include"Window_mgr.h"
//调用了非本类的函数
void Window_mgr::show(){
    for(auto temp:screens)
        temp.dispaly(cout);
}

Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen &s){
    screens.push_back(s);
    //返回其编号
    return screens.size()-1;
}

void Window_mgr::clear(ScreenIndex i){
    Screen &s = screens[i];
    cout<<"clear: "<<s.height<<" "<<s.width<<endl;
    s.contents = string(s.height*s.width,' ');
}

class B.h

#ifndef SCREEN
#define SCREEN
#include<iostream>
#include<string>
#include"windows.h"
//#include"Window_mgr.h"
using namespace std;
//别名
typedef string::size_type pos;
class Screen
{
private:
    //光标所在位置
    pos cursor = 0,height = 0,width = 0;
    //光标所在位置的字符
    string contents;
    mutable size_t access_ctr;
    //输出函数
    void do_display(ostream &os) const{
        os<<contents;
    }
public:
    //声明友元类,即可以调用Screen类中的函数
    friend class Window_mgr;
    Screen() = default;
    //给定屏幕的尺寸,声明一个一维数组,用于存放字符
    Screen(pos ht,pos wd, char c):height(ht),width(wd),contents(ht*wd,c){};
    //隐式内联,获取光标处的字符
    char get() const{return contents[cursor];}
    //显式内联,函数重载 获取给定处的字符
    char get(pos ht,pos wd) const;
    //之后设置为内联,移动光标
    inline Screen &move(pos r,pos c);
    //计数
    void some_number() const;
    //设置光标所在的字符
    Screen &set(char);
    //设置其他任意位置的字符
    Screen &set(pos,pos,char);
    //打印 非常量
    Screen &dispaly(ostream &os);
    //打印 常量
    const Screen &display(ostream &os) const; 
};

//r行  c列
//定义处设置内联,把光标移至指定位置
inline Screen& Screen::move(pos r,pos c){
    pos row = r * width;
    cursor = row + c;
    //以左值的方式返回
    return *this;
} 
#endif

class B.cpp

#include"Screen.h"

//返回给定列的字符 
char Screen::get(pos r,pos c) const{
    pos row = r * width;
    return contents[row+c];
}

void Screen::some_number() const{
    ++access_ctr;
}

Screen& Screen::set(char c){
    contents[cursor] = c;
    return *this;
}
Screen& Screen::set(pos r,pos col,char ch){
    contents[r*width+col] = ch;
    return *this;
}
Screen & Screen::dispaly(ostream &os){
    do_display(os);
    return *this;
}
const Screen& Screen::display(ostream &os) const{
    do_display(os);return *this;
}

main.cpp使用

Screen myScreen(5,5,'x');
myScreen.move(4,0).set('#').dispaly(cout);
cout<<endl;
myScreen.dispaly(cout);
cout<<endl;

cout<<"Window"<<endl;
Window_mgr Screens;
int count = Screens.addScreen(myScreen);
Screens.show();
cout<<"myscreen number "<<count <<endl;

结果
结果

2.基础类学习

class sales_data.h

#ifndef SALA_DATA
#define SALA_DATA
#include<iostream>
#include<string>
using namespace std;
class sales_data
{
private:
    string bookno;//书号
    double units_sold;//销售的册数
    double price;
    double revenue;//总销售额
    double average;

public:
    // 无参构造函数
    sales_data();
    //sales_data() = deflaut 默认构造函数;
    //有参数的构造函数
    sales_data(string b,int u,double p):bookno(b),units_sold(u),price(p){};
    //运算符重载 友元函数,其他类调用该类中的私有数据,返回的是引用类型,必须保证是引用,否则调用构造函数,输入输出的对象不是一个,
    friend istream& operator >> (istream &,sales_data &);
    friend ostream& operator << (ostream &,sales_data &);
    friend sales_data operator + (sales_data &lhs,sales_data & rhs);
    //引用不会调用拷贝构造函数,在内存中不产生被返回值的副本
    sales_data& operator = (const sales_data &);
    friend bool operator == (sales_data &,sales_data &);
    sales_data &operator += (const sales_data &);
    double avg_price();
    //声明isbn函数,返回书籍号
    string isbn() const;
    //一个combine成员函数,用于将一个sales_data对象加到另一个对象上
    sales_data& combine(const sales_data &);
    //声明sales_data类的非成员接口函数
    //一个read函数,将数据从istream读入到sales_data对象中
    friend istream & read(istream &,sales_data &);
    //一个add函数,执行两个对象的加法
    //friend sales_data add(const sales_data &, const sales_data &);
    //sales_data add(const sales_data &, const sales_data &);
};
sales_data add(const sales_data &, const sales_data &);
#endif

class sales_data.cpp

#include"Sales_data.h"

// 加default 就不需要赋初始值
sales_data::sales_data(){
    bookno = "null";
    units_sold = 0;
    price = 0.0;
}
//接下来的四个函数都是友元函数,其他类的,不需要加class的定义域
istream& operator >>(istream &input,sales_data &s){
    input >> s.bookno >> s.units_sold >> s.price;
    if(input){
        s.revenue = s.units_sold * s.price;
    }
    return input;
}

ostream& operator << (ostream &output,sales_data &s){
    output << s.bookno <<" "<< s.units_sold << " "<<s.revenue<<" "<<s.avg_price()<<endl;
    return output;
}
//返回的是函数内部的变量,需要是拷贝值
sales_data operator + (sales_data &lhs,sales_data &rhs){
    sales_data ret;
    ret.bookno = lhs.bookno;
    ret.units_sold = lhs.units_sold + rhs.units_sold;
    ret.avg_price();
    return ret;
}

bool operator == (sales_data &lhs,sales_data &rhs){
    return lhs.units_sold == rhs.units_sold && lhs.price == rhs.price;
}
//重载赋值运算符  本类中声明的函数
sales_data& sales_data::operator = (const sales_data &lhs){
    bookno = lhs.bookno;
    units_sold = lhs.units_sold;
    price = lhs.price;
    return *this;
}

sales_data& sales_data::operator += (const sales_data &rhs){
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}

double sales_data::avg_price(){
    average = revenue / units_sold;
    return average;
}

string sales_data::isbn() const{
    return bookno;
}
//和重载的+一致,只要返回的不是该函数内部的都加引用
sales_data &sales_data::combine(const sales_data &rhs){
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
} 

istream & read(istream &input,sales_data &rhs){
    input >> rhs.bookno >> rhs.units_sold >> rhs.price;
    rhs.revenue = rhs.units_sold * rhs.price;
    return input;
}
sales_data add(const sales_data &lhs,const sales_data &rhs){
    sales_data sum = lhs;
    sum.combine(rhs);
    sum.avg_price();
    return sum;
}

3.静态成员与静态函数

student.h

#ifndef STUDENT
#define STUDEBT
#include<iostream>
using namespace std;
class Student{
public:
    Student(int n,int a,float s):num(n),age(a),score(s){}
    void total();
    //声明静态成员函数,求取平均分,这写static,后面就不用写了
    static float average();
private:
    int num;
    int age;
    float score;
    //计算总分
    static float sum;
    //统计人数
    static int count;
};
#endif

student.cpp

#include"Student.h"

void Student::total(){
    sum += score;
    count++;
}
float Student::average(){
    return (sum/count);
}

main.cpp

Student stu[3]={
        Student(1001,18,70),
        Student(1002,19,78),
        Student(1005,20,98),
    };
int n;
cout<<"how many students' grates? ";
cin>>n;
for(auto &it : stu){
   it.total();
}
cout<<"average = "<<Student::average()<<endl;

结果
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值