今天早上学妹说运算符重载好难,让我帮她看两道题目:
呜呜呜,我也觉得难啊。我再一看题目,杂连模板都整出来了。这现在大学进度这么快么?不过,为了好好表现一下,我还是硬着头皮上了。
第一题
1. 涉及知识点
这道题目主要涉及的要点有继承关系下构造函数,多态(基类指针指向派生类对象),运算符重载(+=、<<)等等。
2. 代码
#include<iostream>
#include<string>
class Animal{
protected:
std::string name;
public:
Animal(std::string n):name(n){}
virtual Animal& operator += (int growAge){return *this;}
friend std::ostream& operator << (std::ostream &os, Animal *p){
p->printInfos();
return os;
}
virtual void printInfos() = 0;
};
class Horse:public Animal{
int age;
public:
Horse() = default;
Horse(std::string n, int h):Animal(n),age(h){}
virtual void printInfos()override{
std::cout<<name<<": "<<age<<" years old"<<std::endl;
}
};
class Pig:public Animal{
int age;
public:
Pig() = default;
Pig(std::string n, int p):Animal(n),age(p){}
virtual Pig& operator += (int growAge)override{
std::cout<<"Pig: "<<name<<" grows old"<<std::endl;
this->age += growAge;
return *this;
}
virtual void printInfos()override{
std::cout<<name<<": "<<age<<" years old"<<std::endl;
}
};
3. 小结
我晓得多态情况下,基类指针指向派生类对象可以调用派生类的成员函数,所以我比较朴素的在两个派生类中重载了流输出运算符,以至于我运行语句cout<<animal[0]<<animal[1]时输出的总是00BC21F0和00BC1F70两个地址。由于忽略了友元函数不算类的成员函数这一点,所以基类Animal的指针还是使用基类默认的输出行为,故显示的是指针数组animal的元素值。
于是我在基类中用纯虚函数声明了一个输出接口,然后在派生类中各自实现,再再基类中重载流输出运算符,并通过基类指针调用该接口,由于多态,实际上调用的是实际对象的接口实现。
第二题
1. 涉及知识点
这道题目主要涉及的要点有运算符重载([]、<<),模板等等。
2. 代码
#include<iostream>
template<class T>{
T x,y,z;
Point3D() = default;
Point3D(T a, T b, T c):x(a),y(b),z(c){}
friend std::ostream& operator << (std::ostream &os, const Point3D &p){
os<<p.x<<" "<<p.y<<" "<<p.z<<std::endl;
return os;
}
};
template<class T, int len>
class Skeleton{
Point3D<T>joints[len];
public:
Skeleton(Point3D<T>*j){
for(int i=0;i<len;++i){
joints[i]=j[i];
}
}
Point3D<T>& operator [] (const char *str){
if(str=="HEAD"){
return joints[0];
}
else if(str=="NECk"){
return joints[len - 1];
}
}
};
3. 小结
这道题目粗一看有模板,其实就是“水货”,主要还是运算符重载。再有一点要注意的是,在自定义了构造函数后,编译器并不会再合成默认构造函数。而Skeleton的对象中包含复合类成员数组joints,需要调用Point3D类的默认构造函数,所以要注意添加。但这个问题在编译期间就可以被编译器指出从而被修正。