- 定义在类内部的函数是隐试的inline函数
- std::string isbn() const { return bookNo;}
这里的const实在修改隐式this指针的类型
练习 7.4:编写一个名为Person的类。使其表示人员的姓名和住址。使用string对象存放这些元素,接下来的练习将不断充实这个类的其他特征
#include
#include
using namespace std;
struct Person
{
string getName() const {return name;}
//name定义在getName之后,依旧可以使用name。因为会首先编译成员声明。然后才轮到成员函数体
string getAddress() const { return address;}
string name;
string address;
};
练习7.9:继续添加读取和打印的Person对象操作
#include
#include
using namespace std;
struct Person
{
string getName() const {return name;}
string getAddress() const { return address;}
string name;
string address;
};
std::istream & read(std::istream & is, Person & item)
{
is >> item.name >> item.address;
return is;
}
std::ostream & print(std::ostream & os, const Person & item)
{
os << item.name << " " << item.address << " ";
return os;
}
- 当你定义了一个构造函数后。默认的构造函数便不会在执行
#include
#include
using namespace std;
struct Person
{
// Person() = default; //这里
Person(const string n, const string a) : name(n), address(a) { }
string getName() const {return name;}
string getAddress() const { return address;}
string name;
string address;
};
std::istream & read(std::istream & is, Person & item)
{
is >> item.name >> item.address;
return is;
}
std::ostream & print(std::ostream & os, const Person & item)
{
os << item.name << " " << item.address << " ";
return os;
}
int main()
{
Person x; //这里
//上面那一行会报错,因为没有办法初始化,所以需要一个默认的构造函数Person() = default;
cout << x.name;
}
struct 和 class
- struct默认是public
- class默认是private
7.16:在累的定义中对于访问说明符出现的位置和次数有限定吗?
- 一般来说没有
练习7.17: 使用class和struct有什么区别
- 唯一的区别就是默认的访问权限
练习7.18:封装是何含义?它有什么用处?
- 定义一系列的接口,对用户隐藏实现的细节。用户只要去调用接口就行
友元
友元声明只能出现在类定义内部,友元不是类成员也不受它所在区域访问控制级别的约束。
练习7.22:修改你的Person类使其隐藏实现的细节
#include
#include
using namespace std;
struct Person
{
friend std::istream & read(std::istream & is, Person & item);
friend std::ostream & print(std::ostream & os, const Person & item);
string getName() const {return name;}
string getAddress() const { return address;}
Person() = default;
Person(const string n, const string a) : name(n), address(a) { }
private:
string name = "";
string address = "";
};
std::istream & read(std::istream & is, Person & item)
{
is >> item.name >> item.address;
return is;
}
std::ostream & print(std::ostream & os, const Person & item)
{
os << item.name << " " << item.address << " ";
return os;
}
友元声明
在一个类允许另一个类访问此类包括私有成员在内的所有成员
struct X
{
friend void f(); //友元函数可以定义在类的内部
X() {f();} //错误:f还没有被声明
void g();
void h();
};
void X::g() { return f();} //错误:f还没有被声明
void f(); //声明f
void X::h() { return f();} //正确f声明了
构造函数
Sales_data::Sales_data(const string &s, unsigned cnt, double price)
{
bookNo = s;
units_sold = cnt;
revenue = cnt * price;
/*这种写法不好,比较草率,属于先初始化。然后再去赋值*/
}
练习7.36: 下面的初始值是错误的,请找出问题所在并尝试修复它。
struct X
{
X (int i, int j): base(i), rem(base % j) { }
int rem, base;
顺序问题。初始化的顺序按照出现先后。先会出事rem发现base没有
}
编译器会进行隐式的类类型转换将string变成sales_data不过,可以用explicit来阻止。不是绝对可以使用显示的强转
练习7.49: 对于combine函数的三种不同声明,当我们调用i.combine(s)时分别发生什么情况?其中i时Sales_data,而s时一个string对象
a) Sales_data &combine(Sales_data);//正常执行
b)Sales_data &combine(Sales_data&);//执行失败引用想要引用常量必须const
c)sales_data &combine(const Sales_data&) const;//可以,不过里面会有变量的修改所以还是失败
类的静态成员
- 使用static声明,静态成员可以是public或private
- 类的静态成员函数,可以在外部定义。不过在外部定义不要加static
- 类内初始化。必须是字面值类型constexpr。初始值不需是常量表达式。
- 即使在类部初始化了也应该在外部定义一下
#include
#include
using namespace std;
class Account
{
public:
void calculate() { amount += amount * intersetRate;}
static double rate() { return intersetRate; }
static void rate(double);
private:
std::string owner;
double amount;
static double intersetRate;
static double initRate() { return 5;};
};
double Account::intersetRate = initRate(); //在定义一个intersetRate对象,是类的静态成员。
//从类名开始,这条定义语句的剩余部分都位于作用域之类了。可以直接使用私有initRate。初始化
int main(void)
{
double r;
r = Account::rate();
cout << r;
Account::rate(10);
cout << Account::rate();
return 0;
}
void Account::rate(double newRate)
{
intersetRate = newRate;
}