CPP-10-对象和类

声明一个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Stock
{
private:
string company;
long shares;
double share_val;
double total_val;
void set_tot() {
total_val = shares * share_val;
}

public:
void acquire(const string &co, long n, double pr);
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};

关键字privatepublic描述了对类成员的访问控制。使用类对象的程序都可以直接访问公有部分,但只能通过公有成员函数来访问对象的私有成员,默认是private私有成员

cpp_class_0729_2253

成员函数的函数头使用作用域运算符解析(::)来指出函数所属的类。例如,update() 成员函数的函数头如下

1
void Stock::update(double price);

构造与析构

1
2
3
4
5
6
7
8
9
int year = 2001;
struct thing
{
char *pn;
int m;
};
thing amabob = {"wodget", -23};
//Stock hot = {"stock host", 200, 50.23};
}

上述代码中 thing 结构体可以直接声明对象,但是 Stock 无法实例化对象,会提示 没有与参数列表匹配的构造函数 "Stock::Stock" 实例,原因是数据的访问状态是私有的,程序不能直接访问。这个时候就可以用构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Stock(const string &co, long n, double pr)
{
company = co;
if(n < 0) {
shares = 0;
} else {
shares = n;
}
share_val = pr;
}

Stock hot = {"stock host", 200, 50.23};
Stock niu = Stock{"stock host", 200, 50.23};
Stock *nnm = new Stock{"stock host", 200, 50.23};

上述三种方式使用构造函数,但是需要一个特殊的地方

1
2
//类 "Stock" 不存在默认构造函数
Stock st;

也就是说 Stock st;其实是使用的默认构造函数,如果不编写构造函数的时候是可以的,但是如果声明了构造函数,那么就不能直接声明类实例。为了解决这个问题可以将已有构造函数使用默认值

1
2
3
4
Stock(const string &co = "Error", long n = 2, double pr = 3.145)
{
//...
}

也可以使用一个默认构造函数

1
Stock();

由于只能有一个默认构造函数,所以上述两种方法只能用一种

当程序过期的时候,程序将自动调用一个特殊的成员函数–析构函数与构造函数不同的是,析构函数没有参数

1
2
3
4
5
//~Stock();
~Stock()
{
cout << "Bye, " << company << "!\n";
}

调用析构函数时机由编译器决定,通常不显示地调用析构函数

  • 如果创建的是静态存储类对象,则其析构函数将在程序结束时被调用
  • 如果创建的是自动存储类对象,则其析构函数将在程序执行完代码块自动被调用
  • 如果对象是通过 new 创建时,则它将驻留在栈内存或自由存储区中,当使用 delete 来释放内存时,其析构函数将自动被调用

由于在类过期时析构函数将自动被调用,因此必须有一个析构函数。如果没有提供析构函数,编译器将隐式地声明一个默认析构函数

可以使用对象数组声明多个对象

1
2
3
4
5
6
7
const int STKS = 4;
Stock stocks[STKS] = {
Stock{"boject 1", 12, 111},
Stock{"boject 2", 12, 111},
Stock{"boject 3", 12, 111},
Stock{"boject 4", 12, 111},
};

const 成员函数

1
2
const Stock land = Stock{"Kluudgehorn Properties"};
land.show();

提示 对象含有与成员 函数 "Stock::show" 不兼容的类型限定符C/C++(1086),stock11.cpp(8, 5): 对象类型是: const Stock,因为 代码无法确保调用对象不被修改——调用对象和const一样, 不应被修改。

为了保证不会修改调用对象,C++的解决方法是将const关键字 放在函数的括号后面

1
2
3
4
5
6
void show() const;

void Stock::show() const
{
cout << "Number of shares purchased" << endl;
}

this指针

有时候方法可能涉及到两个对象,在这种情况下需要使用C++的this指针

例如:该函数隐式地访问一个对象,而显式地访问另一个对象,比较之后返回其中一个对象的引用

1
const Stock & topval(const Stock & s) const;

括号中的const表明,该函数不会修改被显式地访问的对象;而括号后的const表明,该函数不会修改被隐式地访问的对象。 由于该函数返回了两个const对象之一的引用,因此返回类型也应为 const 引用

假设要对Stock对象stock1和stock2进行比较,并返回其中一个则

1
2
top = stock1.topval(stock2);
top = stock2.topval(stock1);

第一种格式隐式地访问stock1,而显式地访问stock2;第二种格式显式地访问stock1,而隐式地访问无论使用哪一 种方式,都将对这两个对象进行比较,并返回其中一个对象

1
2
3
4
5
const Stock & Stock:topval(const Stock & s) const
{
if(s.total_val > total_val) return s; //return argument object
else return *this; //invoking object
}

使用被称为this的特殊指针。this指针指向用来调用成员函数的对象(this被作为隐藏参数传递给方法)。

参考链接

  1. 《C++ Primer Plus》