感觉这个部分比较重要而且内容比较多,单独写一篇文章
1 对类的初印象[incomplete]
和C程序不一样,在C++中你首先要关心的并不是通过怎样的代码来实现一个类,而是一个类所能进行的所有操作、以及这些操作的效果。我们可以先用伪代码来写出类的定义,再在main函数中使用这个类。
example.h
class Sales_item:
商品
operation <<:
输入名称、单价、购买数量
operation <<:
输出名称、单价、购买数量、总价格
operation +:
名称相同时,单价修改为平均价格,购买数量修改为总数量
名称不同时,提示错误
operation =:
修改名称、单价、购买数量
example.c
#include <iostream>
#include "example.cxx"
int main()
{
Sales_item book;
std::cin >> book;
std::cout<<book<<std::endl;
Sales_item book2;
std::cin>>book2;
std::cout<<book+book2<<std::endl;
book=book2;
std::cout<<book<<std::endl;
}
2 static数据成员、static成员函数
如果我们要求一个类的所有对象共享一个数据,我们可以把这个数据定义成static类型的成员数据;同样,如果希望所有的对象共享一个成员函数,我们可以定义static 成员函数
调用static成员函数的三种方法:
假设animal类有一个成员函数 animal::population()
animal guest;
animal* guestAddress=&guest;
guest.population();
guestAddress->population();
animal::population();
3 const成员函数
定义方式:在结尾加关键字“const”
const_function_type myConstFunction(...) const
含义:这个函数不会改变对象的成员数据
标记为mutable的成员数据除外:const对象的mutable成员数据也可以被修改,而且const成员函数可以修改mutable成员数据。
4 static objects of some class/singleton
有时候我们在程序中需要用到一些相关的常量,这些常量都和某一个具体对象相关,例如太阳这个对象——我们希望能在整个程序中随时使用太阳的质量、半径、表面重力加速度、热功率等等,我们还希望能随时打印太阳的所有参数。我们可以定义一些全局常量,但是这样并不符合面向对象编程的思想,而且也不能体现这些参数之间的关系。而最好的解决办法就是创建一个只有一个对象(singleton)的类。
先看例子:
http://www.codeproject.com/Articles/1921/Singleton-Pattern-its-implementation-with-C
可以看到这个类有一个static成员数据single,而且这个成员数据恰好是Single类类型的。
由于static类型的数据在main函数开始前就已经初始化好了,
5 静态成员数据赋初值
赋初值需要1 在内存中分配空间 2 将初始化数据写入所分配的内存空间
假设有一个类
MyClass.h
#include "anotherClass.hh"
class MyClass
{
public:
static int staticIntObject;
static anotherClass* staticAnotherClassObject;
int IntObject;
anotherClass* AnotherClassObject;
static bool initialize();
private:
MyClass(){}
~MyClass(){}
};
anotherClass.hh
class anotherClass
{
public:
anotherClass(){}
~anotherClass(){}
};
在MyClass.cc文件中,由于构造函数是私有的:
MyClass MyClassObject;语句是非法的。因为需要调用构造函数。
MyClass* MyClassObjectPointer=new MyClass;是非法的。因为需要调用构造函数。
MyClass* MyClassObjectPointer;是合法语句,不会调用构造函数。
对于static类型的数据成员:
编译器会在整个程序中搜索静态成员数据的初始化语句,如果没有找到则无法初始化。见这个:
http://blog.youkuaiyun.com/lwl_ls/article/details/3919028
在类类定义之外给静态成员数据赋初值
这是因为被static声明的类静态数据成员,其实体远在main()函数开始之前就已经在全局数据段中诞生了(见《Inside The C++ Object Model》page247)!其生命期和类对象是异步的,(而且静态语意说明即使没有类实体的存在,其静态数据成员的实体也是存的)这个时候对象的生命期还没有开始,如果你要到类中去初始化类静态数据成员,让静态数据成员的初始化依赖于类的实体,,那怎么满足前述静态语意呢?难道类永远不被实例化,我们就永远不能访问到被初始化的静态数据成员吗?
MyClass.cc
#include "MyClass.hh"
#include "anotherClass.hh"
int MyClass::staticIntObject=1;
anotherClass MyClass::staticAnotherClassObject; //anotherClass类型静态数据成员赋初值,会调用构造函数
bool MyClass::initialize() //无需重复static保留字
{
if(staticAnotherClassObject=new anotherClass()) //此时会调用anotherClass的构造函数
return true;
else
return false;
}
main.cc
#include <iostream>
#include "MyClass.hh"
int main()
{
MyClass::initialize();
std::coud<<MyClass::staticIntObject<<std::endl;
return 0;
}
6 纯虚函数
在类声明体中某一成员函数形参表后加“=0”表示声明此成员函数为纯虚函数。
只有虚函数才能是纯虚函数。
7 抽象类
如果一个类中至少有一个成员函数为纯虚函数,则这个类为抽象类。
不能定义抽象类类型的对象、或给指向抽象类类型的指针分配空间,但是可以定义一个(未初始化或空的)指向抽象类类型的指针。
* virtual 虚函数 [incomplete]
先要解释动态绑定。假设有两个类Animal类和Human类,其中Human类是基类Animal的一个派生类。我们可以定义一个对象guest为Animal类:
Animal guest;
然后又定义两个对象
Animal dog;和Human Jack;
假设Animal类下有一个成员函数为sayhello(),其内容是Animal::sayhello(){cout<<"Hi!"<<endl;},则Human类会继承这个成员函数。
现在我们在Human类中重定义这个函数为Human::sayhello(){cout<<"Let's shake hands."<<endl;};
现在我们来做一个实验
guest=dog;
guest.sayhello();
guest=Jack;
guset.sayhello();
结果怎么样?
我们现在在原来Animal类声明中在sayhello的声明前加上关键字 virtual,再来一遍,结果又怎么样?
#ifndef def
#define def 1
#include <iostream>
using namespace std;
class Animal {
Public:
void sayhello(){cout<<"Hi!"<<endl;}
};
class Human:public Animal
{
Public:
void sayhello(){cout<<"Let's shake hands."<<endl;}
};
#endif
#include <iostream>
#include "def.hh"
int main()
{
Animal guest;
Animal dog;
Human Jack;
guest=dog;
guest.sayhello();
guest=Jack;
guest.sayhello();
return 0;
}
编译还没通过,慢慢改