一、派生类以及构造函数
例子:
#include <iostream>
using namespace std;
//
class Counter
{
public:
Counter():count(0) {}
Counter(int con):count(con) {}
unsigned int getcount()
{
return count;
}
void operator ++ ()
{
++count;
}
protected:
unsigned int count;
};
class CountDn :public Counter
{
public:
//CountDn():Counter() {}
//CountDn(int c):Counter(c) {}
Counter operator -- ()
{
return Counter(--count);
}
};
//
int main()
{
CountDn c1,c2=2;
--c2;
++c1;
cout<<"c1="<<c1.getcount();
cout<<"\nc2="<<c2.getcount()<<endl;
return 0;
}
从上例中:
1)记住某个类的成员函数总是能访问类的其他成员,不管类是共有的、保护的还是私有的。但是外部声明的对象只能调用公共的类成员。
2)如果类中的成员是公共后者是保护的,那么派生类的成员函数可以访问他,但是private的成员是不能访问的(即不可见)。
3)派生类构造函数:
① 首先我们要知道编译器在建立派生类的对象时只会用到一个来自基类的、不带参数的构造函数来代替,但是像单参数这样复杂的构造函数是不被允许的。
② 我们要像建立一带参数的派生类对象就必须建立派生类的构造函数,就像CountDn(int c):Counter(c) {} 这样:通过调用基类的构造函数,使参数c从CountDn传递到Counter,用来初始化对象。
另外:
像:派生类中的构造函数
DistSign(int ft,float in,posneg sg=pos):Distance(ft,in)/*,sign(sg)*/
{sign=sg; }
上面两种方式都是合法的;
此时既可以是两个参数,也可以使三个参数的构造函数。第三个参数是符号,可以选择是pos还是neg,它默认是pos。
二、重载成员函数
这里模仿一个简单的数据存储设备--堆栈
#include <iostream>
using namespace std;
//
class Stack
{
protected:
static const int MAX=3;
int str[MAX];
int top;
public:
Stack()
{
top=0;
}
void push(int var)
{
str[top++]=var;
}
int pop()
{
return str[--top];
}
};
class Stack2:public Stack
{
public:
void push(int var)
{
if (top>=MAX)
{
cout<<"error:stack is full\n"; exit(1);
}
Stack::push(var);
}
int pop()
{
if (top<=0)
{
cout<<"error:stack is empty\n"; exit(1);
}
return Stack::pop();
}
};
//
int main()
{
Stack2 s1;
s1.push(11);
s1.push(22);
s1.push(33);
s1.push(44); //错误
cout<<s1.pop()<<endl;
cout<<s1.pop()<<endl;
cout<<s1.pop()<<endl;
cout<<s1.pop()<<endl; //错误
return 0;
}
1)在上面的函数中,push和pop有相同的名称,相同的参数和相同的返回类型,那原则是:当基类和派生类中存在相同的函数时,执行派生类中的函数(派生类对象遵循的规则)。基类的对象当然会使用基类的函数,因为对派生类不可见。
2)派生类中的函数如何使用基类的函数:从Stack::push(var);和 return Stack::pop(); 看出应该使用域分解运算符(::)。
二、类的聚合
上面说的派生指的是一种从属关系,而聚合是一种“部分-整体”的关系。
如:
class A
{};
class B
{
A objA; //A的对象在B类中
};