文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

c++primer类详解

2024-04-02 19:55

关注

类的基本思想是数据抽象和封装。

数据抽象是依赖接口和实现分离的编程技术。

1. 定义抽象数据类型

1.1 设计Sales_data类

1.2 定义类相关的非成员函数


Sale_data s1;
Sale_data s2=s1;//s2拷贝了s1的成员

1.3构造函数


class A{
//定义了一个实参为string的构造函数
//此时,编译器不会合成默认构造函数
	A(std::string a){}
}
A a;//错误,没有默认构造函数
A a1(std::string("小黑"));//只能用string参数

若在类内部,则默认构造函数时内联的,若在类外部,默认不是内联的。


class A{
	A()=defualt;
}
A a;//正确,编译器生成默认构造函数

class Sales_data{
	Sales_data(const std::string &s,unsigned n,double p):
	bookNo(s),units_sold(n),revenue(p*n){}
	//当编译器不支持类内初始值时,可用如下方法定义
	Sales_data(const std::string &s):
	bookNo(s),units_sold(0),revenue(0){}
}

Sales_data::Sales_data(std::istream cin){
	read(cin,*this);
}

1.4 拷贝、赋值和析构

2 访问控制和封装

public说明符后的成员在整个程序内可以被访问

private说明符后的成员可以被类的成员函数访问

2.1 友元

2.2 类的其他特性

接下来介绍:类型成员、类的成员的类内初始值、可变数据成员、内联成员函数、从成员函数返回*this、如何定义使用类类型、友元类

2.2.1 类成员再探

 在类中定义的类型名字和其他成员一样存在访问限制,可以是public或者private

类别名必须先定义后使用

(回忆:类成员变量可以在类成员函数之后定义,但是在类函数中使用,原因是编译器先编译类成员变量后边一类成员函数)

类型成员通常出现在类开始的地方


class Screen{	
	public:
	//等价于 using pos = std::string::size_type
	typedef std::string::size_type pos;
}

定义在类内部的函数是自动inline的,定义在类外部的函数,若需要声明内联函数,要加上inline;inline成员函数也应该和相应的类定义在同一个头文件夹


inline 
Screen& Screen::move(pos r,pos c){
	pos row = r*width;
	cursor = row + c;
	return *this; 
}

class Screen{
public void some_member() const;
private:
	mutable size_t access_ctr;//使用mutable声明可变数据成员
}
void Screen::some_member() const {
	++access_ctr;//即使在const成员函数中,仍然可以修改可变数据成员
}

2.2.2 返回*this的成员函数


inline Screen &Screen::set(char ch){
	content[cursor] =ch;
	return *this;
}
inline Screen &Screen ::move(pos r,pos col){
	cursor= r * width + col ;
	return *this;
}
Screen s(3,2,'');
//move函数返回s本身,所以可以接着调用set函数
//并且move函数返回的是Screen的引用,若返回的不是引用,则会返回一个新的Screen对象
s.move(3,2).set('!');

编写函数display打印Screen中的contents,因为只是展示,不需要修改值,所以这应该是一个const函数。

但是希望实现在展示后,能移动光标:s.display().move(2,3)。这要求display返回的值是可以修改的,所以这不应该是const函数。

基于const重载,可以根据Screen对象是否是const来进行重载。


class Screen{
public:
	Screen* display(std::ostream &os){
		do_display(os);
		return *this;
	}  
	const Screen* display(std::ostream &os) const{
		do_display(os);
		return *this;
	} 
private:
	void do_display(std::ostream &os) const{
		os<<content;
	}
}
int main(){
	const Screen cs(3,3,'!');
	Screen s(3,3,'.')
	cs.display();//因为cs是const的,调用第二个const函数
	s.display();//调用第一个非const的函数
}

2.2.3 类类型


class A{
int member;
}
class B{
int member;
}
A a;
B b = a;//错误!!

2.2.4 友元再探

有一个screen类,有私有成员content;

有clear函数,可以清除content的内容。

1.先声明clear函数

2.在screen类中将clear函数函数定义为友元函数

3.定义clear函数,使用screen类

有类window,window有私有成员content;友元类 window_mgr需要直接操作content。


#ifndef xxx_H
#define xxx_H
/class 定义///
#endif

struct X{
	friend viod f(){
	X(){f();}//错误,f还没有被定义
	void g();
	void h();
	}
	void X::g(){ return f();}//错误,f还没有被定义
	void f();
	void X::h(){return f();}//正确,f的声明已经在定义中了
};

2.4 类的作用域


//pos的类型声明在window类中,并且返回类型在类的作用域外,因此要使用window::pos
window::pos window::get_pos(){
//在window::get_pos后的所有代码作用域在类内,所以返回cursor,相当于this->cursor
return cursor;
}

2.4.1 名字查找和类的作用域


typedef double Money;
class Acount{
public:
	Money balace(){return bal;}//使用外层定义的Money
private:
	typedef double Money;//错误,不能重新定义Money
	Money bal;
}

double height;
class Window{
	double height;
}
void Window::dummy_fcn(double height){
	double class_height = this->height;
	double para_height = height; 
	double  global_height = ::height;
}

2.5 构造函数再探

2.5.1


//示例危险操作
strcut X{
//实际上按照声明顺序初始化,先初始化rem时,base的值未知
X(int i,int j):base(i),rem(base%j){}
int rem,base;
}

2.5.2 委托构造函数


class Sale_data{
public:
	Sales_data(const std::string &s,unsigned s_num,double price):units_sold(s_num),revenue(s_num*price),BookNo(s){}
	Sales_data():Sales_data("",0,0){}//委托给上一个构造函数
}

2.5.3 默认构造函数的作用

 1.块作用域内不使用任何初始值定义的一个非静态变量或者数组时

2.类本身含有类类型的成员且使用合成的默认构造函数

3.类类型成员没有在构造函数初始值列表中显式初始化时

1.初始化数组时,提供的初始值数量少于数组大小

2.不使用初始值定义一个局部变量时

3.书写形如T()的表达式显式请求值初始化时,其中T是类型名。如vector接受一个实参说明vector的大小

2.5.4 隐式的类类型转换


vector<string> str_vec;
//需要push一个string,但传参一个字符串。这里使用了string的转换构造函数
str_vec.push_back("小黑~");

//Sales_data有参数为string的构造函数
//Sales_data的combine为方法:
//Sales_data & Sales_data::combine(const Sales_data& );
Sales_data item;
item.combine("无限~")//错误,只允许一步构造
item.combine(string("无限~"))//正确,只有string到Sales_data的一步隐式构造转换

class Sales_data{
explicit Sales_data(const string&):bookNo(s){};
...//其他声明
}
item.combine(string("无限~"));//错误,explicit阻止了隐式转换

explicit函数只能用于直接初始化


//Sales_data的构造函数:explicit Sales_data(const string&):bookNo(s){};
string bookNo = "001";
Sales_data item1(bookNo);//正确,直接初始化
Sales_data item2 = bookNo;//错误,拷贝初始化

尽管编译器不会将explicit的构造函数用于隐式转换过程,但是可以使用显式强制转化


string bookNo ="001";
item.combine(bookNo);//错误,explicit阻止了隐式转换
item.combine(static_cast<Sales_data>(bookNo));//正确,强制转换

2.5.5 聚合类

1.所有成员都是public的

2.没有定义任何构造函数

3.没有类内初始值

4.没有基类,也没有virtual函数


class Data{
public:
	int ival;
	string s;
	}
//顺序一定相同
Data val1={0,"孔子"};		

2.5.6 字面值常量

1.数据成员都是字面值类型

2.类必须含有一个 constexpr构造函数

3.使用默认定义的析构函数

4.如果一个数据成员含有类内初始值,则该初始值必须是一条常量表达式;如果数据成员属于某种类类型,则初始值必须使用自己的constexpr构造函数


class Data{
public:
	constexpr Data(int para_i,string para_s):ival(para_i),s(para_s){}
	int ival;
	string s;
	}
constexpr Data data(1,"吃烤肉");

1.6 类的静态成员


class Bar{
public:
//...
provite:
	static Bar mem1;//正确,static成员可以是不完整类型
	Bar* mem2;//正确,指针成员可以是不完整类型
	Bar mem3;//错误
}

- 静态成员可以作为默认实参

class Screen{
	public:
	Screen& clear(char = bkground)
	private:
	static const char bkground;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯