Posted W-forever

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类相关的知识,希望对你有一定的参考价值。

#include<iostream>
#include<string>
#include<vector>
using namespace std;
//改进使用的sales_data类
/*
1.成员函数的声明必须在类的内部,它的定义既可以在类的内部也可以在类的外部
2.定义在类内部的函数是隐式的inline函数
3.紧跟在参数列表后面的const表示this是一个指向常量的指针,像这样使用const成员函数被称为常量成员函数
4.常量对象以及常量对象的引用或指针都只能调用常量成员函数
5.在类的外部定义的成员的名字必须包含它所属的类名
6.在定义与类相关的非成员函数时,定义方式与其他函数一样,如果函数在概念上属于类但是不定义在类中,则它一般与类的声明在同一个文件中

*/

//定义read和print函数
/*
istream &read(istream &is, Sales_data &item)
	double price = 0;
	is >> item.bookNo >> item.uunits_sold >> price;
	item.revenue = price * item.units_sold;
	return is;


ostream &print(ostream &os, const Sales_data & item)
	os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
	return os;

//有一点疑惑,为什么不直接用cin和cout而要创建is和os对象
	*/

//构造函数
//不同于其他的成员函数,构造函数不能被声明为const的,当我们创建类的一个const对象,直到构造函数完成初始化的过程,对象才能真正获取常量属性,因此,构造函数在const对象的构造过程中可以想其写值
/*
1.只有类没有声明任何构造函数,编译器才会自动生成默认构造函数

*/


//Sales_data() = default 的含义
/*
这个函数的声明完全等价于之前的合成默认构造函数
如果这个声明在类的内部,则默认构造函数是内联的,如果他在类的外部,则该成员默认情况不是内联的

*/


////构造函数初始值列表
//Sales_data(const std::string& s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(p* n) ;


//在类的外部定义构造函数
//Sales_data::Sales_data(std::istream& is) 
//	read(is, *this); //read函数的作用是从is中读取一条交易信息然后存入this对象中
//

//拷贝赋值和析构函数
//注意:如果类包含vector和string成员,则其拷贝赋值和销毁的合成版能够正常工作,但是管理动态内存的可通常不能依赖于合成的版本


//class和struct
/*
如果我们使用class关键字,则在定义第一个访问说明符之前的成员是private的,如果我们使用struct关键字,相对应的为public
*/

//友元
/*
1.非成员函数作为类的友元
2.将其他类定义为友元
3.将其他类的成员函数定义为友元
4.如果函数进行了重载,要为重载后的每一个函数分别进行声明
*/

//类成员再探
//Screen类的成员函数
class Screen 
public:
	typedef std::string::size_type  pos;
	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);
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	std::string contents;
;


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


char Screen::get(pos r, pos c) const 
	pos row = r * width;
	return contents[row + c];


//可变成员函数
class Test 
public:
	void some_member() const;
private:
	mutable size_t access_ctr; //即使在一个const对象内也可以发生修改

;
void Test::some_member() const 
	++access_ctr; //通过它我们可以追踪每个成员函数被调用了多少次



//类成员的默认初始值
class Window_mgr 
private:
	std::vector<Screen> screens
		Screen(24, 80, \' \') 
	;
;


//一个const成员函数如果通过引用的方式返回*this,那么他的返回值类型将是常量引用

//基于const的重载
/*
class Screen
public:
	Screen &displaystd::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) constos << contents;
;

Screen myScreen(5, 3);
const Screen blank(5, 3);
myScreen.set(\'#\').display(cout); //调用非常量版本
blank.display(cout); //调用常量版本
*/


//类的声明
class Screen; //这种声明有时候称为前向声明或者不完全类型


//友元声明和作用域
struct X 
	friend void f() ;
	X()  f(); ; // 错误f还没有被声明
	void g();
	void h();
;
//void X::g()  return f() ; //错误 f还没有被声明
void f();
void X::h()  return f(); ;

//如果内层作用域与外层作用域定义了同名的变量,外层作用域的 成员会被隐藏掉,如果我们需要外层作用域的成员,可以通过显示的作用域运算符类进行请求
/*
void  Screen::dummy_fun(pos height)
	cursor = wodth * ::height;

*/

//构造函数的初始值有时候必不可少
//如果成员为const或者是引用时,必须将其初始化,类似的,当成员属于某种类类型而且该类没有定义默认构造函数的时候,也必须将这个成员初始化
class ConstRef 
public: 
	ConstRef(int il);
private:
	int i;
	const int ci;
	int& ri;
;

ConstRef::ConstRef(int il) 
	i = il;
	//ci = il; 错误,不可以给const赋值
	//ri = i; 错误ri没有被初始化
	//这样的话这个代码就是错误


//正确:显示的初始化引用和const成员
ConstRef::ConstRef(int il) :i(il), ci(il), ri(i) ;


//委托构造函数
/*
一个委托构造函数使用它所属类的其他构造函数执行他自己的初始化过程,或者说他吧他自己的一些或者全部职责委托给了其他构造函数
*/

//新手经常犯的错误
/*
Sales_data obj(); //错误,声明了一个函数而非对对象
Sales_data obj2; //正确,obj2是一个对象而非函数
*/

//隐式的类类型转化
/* 只允许一步类类型转化*/

//抑制构造函数定义的隐式转化
/*
我们可以将构造函数声明为explicit加以阻止
class Sales_data
public:
	Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(p * n)
	explicit Sales_data(const std::string &s):bookNo(s);
	explicit Sales_data(std::istrean&);

	//explicit只对一个实参的构造函数有效,需要多个 实参的构造函数不能用于执行隐式转换,所以无需将这些构造函数指定为explicit,
	//explicit关键字只允许类内的构造函数声明处,
	//explicit只能用于直接初始化
	Sales_data item1(null_book); //正确
	Sales_data item2 = null_book; //错误
	https://www.cnblogs.com/zzzsj/p/15930263.html(可以看看这个参考参考)
	*/

//字面值常量类
/*
constexpr函数和返回值必须是字面值类型,处理算术类型,引用和指针外,某些类也是字面值类型
数据成员必须都是字面值类型
类必须至少含有一个constexpr函数
如果一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式,
类必须使用构析函数的默认定义
*/


/*类的静态成员
类的静态成员存在于任何对象之外,对象中不包含任何静态数据成员有关的数据,静态成员函数也不予任何对象绑定在一起他们不包含this指针。
作为结果,静态成员函数不能声明为const的,而且我们也不能在static函数体内使用this指针
*/

int main() 
	system("pause");
	return 0;



以上是关于类的主要内容,如果未能解决你的问题,请参考以下文章

Java 静态成员类 非静态的成员类 局部类 匿名类

JavaSE基础(十 三 )---<内部类>成员内部类,静态内部类,局部内部类,匿名内部类,内部类的意义

Kotlin基础(十三) 嵌套类内部类和匿名内部类

java 内部类和外部类的关系

19-Java-核心类库2-包装类Integer类String类StringBuffer类StringBuilder类

Kotlin基础(十三) 嵌套类内部类和匿名内部类