一、继承类和多态类
1、其实多态中也需要继承这一步,因此两者之间有较大的联系;
2、在有继承的函数中(包括多态),基类
中的成员都最好设置为 protected
;
3、在继承(包括多态)中,子类负责其直接基类的构造,至于如何构造需要看下面; 下面的函数还包括了如何在子类中调用拷贝构造函数
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class Base
{
//friend class Derived;
//private:
//int _a;
protected:
int _a;//上下两种方法都是正确的;最好使用下面的方法;
public:
Base(int a=0):_a(a){cout<<"Base = "<<_a<<" is created."<<endl;}
Base(const Base& p):_a(p._a){cout<<"Base = "<<_a<<" is copied."<<endl;}
~Base(){cout<<"Base = "<<_a<<" is erased."<<endl;}
};
class Derived:public Base
{
private:
int _b;
public:
Derived(int a=0,int b=0):Base(a),_b(b){cout<<"Derived = "<<_b<<" is created."<<endl;}//在子类的构造函数中,首先要记得构造父类;
Derived(const Derived& p):Base(p),_b(p._b){cout<<"Derived = "<<_b<<" is copied."<<endl;}//这里以后记住;
~Derived(){cout<<"Derived = "<<_a<<" "<<_b<<" is erased."<<endl;}//这里是继承,所以有父类的_a,但是,是private类型,所以不可以直接使用,但是如果有friend的话,那么就可以直接用了;如果是protected类型的话就可以直接使用了;
};
int main()
{
int cases, data1, data2;
cin>>cases;
for (int i = 0; i < cases; i++)
{
cin>>data1>>data2;
Base base1(data1), base2(base1);
Derived derived1(data1, data2), derived2(derived1);
}
}
4、子类只负责其直接基类的构造,不负责间接基类的构造
#include <bits/stdc++.h>
using namespace std;
class Square
{
private:
int l;
public:
Square(int ll=0):l(ll){cout<<"Construct Square ("<<l<<")"<<endl;}
int length(){return l;}
int perimeter(){return 4*l;}
int area(){return l*l;}
};
class Rectangle:public Square
{
private:
int w;
public:
Rectangle(int ll,int ww):Square(ll),w(ww){cout<<"Construct Rectangle ("<<length()<<", "<<w<<")"<<endl;}
double width(){return w;}
int perimeter(){return 2*(w+length());}
int area(){return w*length();}
};
class Cuboid:public Rectangle
{
private:
int h;
public:
Cuboid(int ll,int ww,int hh):Rectangle(ll,ww),h(hh){cout<<"Construct Cuboid ("<<length()<<", "<<width()<<", "<<h<<")"<<endl;}
double height(){return h;}
int perimeter(){return 4*(width()+length()+h);}
int area(){return 2*width()*length()+2*width()*h+2*h*length();}
int volume(){return width()*length()*h;}
};
5、有时候不说基类有什么成员,需要自己判断,这个时候要看main函数,子类中总是要给基类赋值,子类中多出的数据即是基类的成员;
(1)在多态中同样适用(一般看如果定义了基类的指针或者引用,把基类的指针或引用绑定到派生类对象上,这个时候,写的函数中需要继承和有虚函数;)
new的括号中为继承的类中构造函数中需要有的所有变量,但是这个并不意味着,这些变量均为继承类中定义的变量,其实,有些甚至所有都为基类的变量,仅仅是通过子类实现基类构造而已,这一点与普通继承类似。
class Vechicle
{
protected:
int speed;
static int numOfVechicles;
public:
Vechicle(int se=0):speed(se){++numOfVechicles;}
static int getNumOfVechicles(){return numOfVechicles;}
virtual~Vechicle(){cout<<"A vechicle is deleted."<<endl;}
virtual void show()=0;
};
int Vechicle::numOfVechicles=0;
class Bike:public Vechicle//这里没有定义新的变量,因为main中说明了在子类构造中需要的变量是一个int类型,但是基类中已经有了int类型的变量,所以,不需要再定义新的变量了;
{
public:
Bike(int nn):Vechicle(nn){}
void show(){cout<<"A bike’s speed is "<<speed<<"km/h."<<endl;}
virtual~ Bike(){cout<<"A bike is deleted."<<endl;}
};
int main()
{
int n;
Vechicle* vechicle;
vechicle = new Bike(n);
}
例如:
#include <iostream>
using namespace std;
class FlyThing
{
protected:
string name;
int x,y;
public:
virtual void fly()=0;
FlyThing(string na="",int xx=0,int yy=0):name(na),x(xx),y(yy){}
void show(){cout<<name<<" at "<<x<<" "<<y<<endl;}
};
class EnemyPlane:public FlyThing
{
public:
EnemyPlane(string na,int xx,int yy):FlyThing(na,xx,yy){}
void fly(){y+=1;}
};
class MyPlane:public FlyThing
{
public:
MyPlane(string na,int xx,int yy):FlyThing(na,xx,yy){}
void fly()
{
char a;
cin>>a;
if(a=='A'||a=='a') x-=1;
else if(a=='S'||a=='s') y+=1;
else if(a=='W'||a=='w') y-=1;
else if(a=='D'||a=='d') x+=1;
}
};
int main()
{
FlyThing **planes;
int numOfEnemplanes, i, x, y, numOfMoves, j;
string str;
cin>>numOfEnemplanes;
planes = new FlyThing*[numOfEnemplanes + 1];
planes[0] = new MyPlane("WUDI", 50, 50);//这里说明了子类的构造中需要有的所有变量;
for(i = 1; i <= numOfEnemplanes; i++)
{
cin>>str>>x>>y;
planes[i] = new EnemyPlane(str, x, y);
}
for (j = 0; j < numOfEnemplanes + 1; j++)
{
planes[j]->show();
}
cin>>numOfMoves;
for (i = 0; i < numOfMoves; i++)
{
for (j = 0; j < numOfEnemplanes + 1; j++)
{
planes[j]->fly();
planes[j]->show();
}
}
return 0;
}
(2)普通继承中,main函数的子类中所有的变量为继承的类中构造函数中需要有的所有变量,但是这个并不意味着,这些变量均为继承类中定义的变量,其实,有些甚至所有都为基类的变量,仅仅是通过子类实现基类构造而已
有时候基类的某些变量在子类中的构造函数中的不到初始化,这个时候,一般在子类中的某一个函数中会实现其初始化(这个时候千万不要在某一个普通的函数中定义变量,还是在该定义变量的位置定义变量)
例如:
#include <bits/stdc++.h>
using namespace std;
class Person
{
protected:
double k;
public:
virtual void input()=0;
virtual void show()=0;
virtual double pay()=0;
};
class Manager:public Person
{
private:
string name;
public:
Manager(string na=""):name(na){}
void input(){cin>>k;}
void show(){cout<<name<<" (Manager)"<<endl;}
double pay(){return k*1000;}
};
class Employee:public Person
{
private:
string name;
double m;
public:
Employee(string na=""):name(na){}
void input(){cin>>k>>m;}
void show(){cout<<name<<" (Employee)"<<endl;}
double pay(){return k*1000*(12+m);}
};
class HourlyWorker:public Person
{
private:
string name;
double m;
public:
HourlyWorker(string na=""):name(na){}
void input(){cin>>k>>m;}
void show(){cout<<name<<" (HourlyWorker)"<<endl;}
double pay(){return k*m;}
};
class CommWorker:public Person
{
private:
string name;
double m;
public:
CommWorker(string na=""):name(na){}
void input(){cin>>k>>m;}
void show(){cout<<name<<" (CommWorker)"<<endl;}
double pay(){return 12*1000*k+m*1000*0.02;}
};
int main()
{
Person *person;
string name, job;
int cases;
cin >> cases;
for(int i = 1; i <= cases; ++i)
{
cin >> job >> name;
if(job == "Manager")
person = new Manager(name);
if(job == "Employee")
person = new Employee(name);
if(job == "HourlyWorker")
person = new HourlyWorker(name);
if(job == "CommWorker")
person = new CommWorker(name);
person->input();
person->show();
cout << " Annual Salary is " << person->pay() << "." << endl;
}
}
二、封闭类(与继承和多态想比,在初始化的地方有不同)
2018年OJ第三次上机作业中的Point和Line中有详细的代码可以更清晰地看出两者的区别;
#include <iostream>
using namespace std;
class Point
{
private:
friend class Line;
double _x,_y;
public:
Point():_x(0),_y(0){}
Point(double x,double y):_x(x),_y(y){}
void show(){cout<<"Point : ("<<_x<<", "<<_y<<")"<<endl;}
~Point(){}
};
class Line
{
private:
Point p1,p2;
public:
Line(double x1,double y1,double x2,double y2):p1(x1,y1),p2(x2,y2){cout<<"Line : ("<<p1._x<<", "<<p1._y<<") to ("<<p2._x<<", "<<p2._y<<")is created."<<endl;}
Line(Point p,Point p3):p1(p),p2(p3){cout<<"Line : ("<<p1._x<<", "<<p1._y<<") to ("<<p2._x<<", "<<p2._y<<")is created."<<endl;}
在封闭类中赋值的时候,一定是给封闭类中的类名赋值,如Base p1(Base类中的对象为int类型),那么就给p1赋值,至于在封闭类中如何定义函数有两种类型,一种是Derived(int a):p1(a)
;另外一种是Derived(Base p):p1(p)
,至于选哪一种方式,则具体看main函数中是什么样子的。
在多态和继承中,则只能是Derived(int a):Base(a)
,而且,必须给封闭类中的类赋值;
例如:
//封闭类
Derived(int a=0,int b=0):c(a),_b(b){cout<<"Derived = "<<_b<<" is created."<<endl;}
Derived(const Derived& p):c(p.c),_b(p._b){cout<<"Derived = "<<_b<<" is copied."<<endl;}
//继承
Derived(int a=0,int b=0):Base(a),_b(b){cout<<"Derived = "<<_b<<" is created."<<endl;}
Derived(const Derived& p):Base(p),_b(p._b){cout<<"Derived = "<<_b<<" is copied."<<endl;}、
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class Base
{
private:
int _a;
public:
Base(int a=0):_a(a){cout<<"Base = "<<_a<<" is created."<<endl;}
Base(const Base& p):_a(p._a){cout<<"Base = "<<_a<<" is copied."<<endl;}
~Base(){cout<<"Base = "<<_a<<" is erased."<<endl;}
};
class Derived
{
private:
Base c;
int _b;
public:
Derived(int a=0,int b=0):c(a),_b(b){cout<<"Derived = "<<_b<<" is created."<<endl;}
Derived(const Derived& p):c(p.c),_b(p._b){cout<<"Derived = "<<_b<<" is copied."<<endl;}
~Derived(){cout<<"Derived = "<<_b<<" is erased."<<endl;}
};
int main()
{
int cases, data1, data2;
cin>>cases;
for (int i = 0; i < cases; i++)
{
cin>>data1>>data2;
Base base1(data1), base2(base1);
Derived derived1(data1, data2), derived2(derived1);
}
}
封闭类
#include <iostream>
using namespace std;
class CPU
{
private:
int _c;
public:
CPU(int c):_c(c){}
int getC(){return _c;}
CPU(const CPU& p):_c(p._c){}
~CPU(){}
};
class Memory
{
private:
int _c;
public:
Memory(int c):_c(c){}
Memory(const Memory& p):_c(p._c){}
int getM(){return _c;}
~Memory(){}
};
class Computer
{
private:
CPU p1;
Memory p2;
string name;
public:
Computer(CPU cpu,Memory me,string na):p1(cpu),p2(me),name(na){}//这里会调用拷贝构造函数,注意给p1赋值的是CPU类型的,而不是int cpu;
void show(){cout<<"This is "<<name<<"’ computer with CPU = "<<p1.getC()<<"GHz, memory = "<<p2.getM()<<"MB."<<endl;}
};