话不多说上复习题
基类的公有成员成为派生类的共有成员。基类的保护成员成为派生类的保护成员。基类的私有成员被继承但是不能访问。
不能继承构造函数,析构函数,赋值运算函数和友元。
如果采用void,可以单个赋值,但是不能连锁赋值; 不用引用速度慢点,返回的时候要复制后,返回副本。
按派生的顺序调用构造函数,最早的构造函数,最早调用。析构函数相反,先搞派生类自己的,再搞基类。
构造函数就算你不写,系统也会给你个默认的空的,所以,从题目的意思是需要构造函数,在实际情况下,你可以不写,也就是没有,但是还是那句话系统会给你个默认的空的。 【注】当我们自定义了一个构造函数时,系统不会再提供一个默认构造函数。
调用的是派生类方法。复制构造函数,赋值运算符在重写的时候,和构造函数一样不用定义成虚函数,但如果你是自己定义的函数,你要在派生类重写,你必须定义为虚函数。
派生类动态分配用new的时候就要重写赋值运算符。
前者可以,后者不可以(想要可以也行:强制转换,向下转换,不安全)
可以将派生类对象赋值给基类,对于派生类新增的不会赋值给基类对象,这个赋值过程用了基类的赋值运算符。反向也行,你得定义转换运算符。
C++允许任何派生而来的类型,我大C++牛皮
按参数传递是什么?是调用基类对象的复制构造函数去生成基类副本,然后副本传给函数。那么在基类对象的复制函数调用生成基类副本的时候,思考下,复制构造函数的形参是什么?是基类的引用对吧?那么基类引用这个形参是不是能传派生类的对象?
不用复制副本,调用复制构造函数再生成个新的对象。初衷按值传递可以不改变原始值,但,随后的学习中你又const其实用引用更快。
a.调用基类的同名方法 b.调用派生类的同名方法
派生类用了基类的私有成员变量,派生类area()覆盖了基类的area(),因为多了一个形参。
码就完事了
main.cpp
#include <iostream> using namespace std; #include "jaycd.hpp" void Bravo(const Cd & disk) { disk.Report(); } int main() { Cd c1("Beatles", "Capitol", 14, 35.5); Classic c2 = Classic("Hongchengkezhan","Jay Chou", "Shiyuexinzuo", 10, 57.17); Cd *pcd = &c1; cout << "Using object directly:\n"; c1.Report(); c2.Report(); cout << endl; cout << "Using type cd * pointer to objects:\n"; pcd->Report(); pcd = &c2; pcd->Report(); cout << endl; cout << "call a funcion with a Cd reference argument:\n"; // 使用Cd引用参数的函数 Bravo(c1); Bravo(c2); cout << endl; cout << "Testing assignment: \n"; Classic copy; copy = c2; copy.Report(); return 0; }.hpp
#ifndef jaycd_hpp #define jaycd_hpp #include <stdio.h> class Cd{ private: char performers[50]; // 表演者 char label[20]; // 标签 int selections; // 选集 double playtime; // 播放时间 public: Cd(); // Cd(const Cd &d); // 没有动态分配不用写就浅复制足够了 Cd(char *s1, char *s2, int n,double x); virtual ~Cd(); virtual void Report() const; // Cd &operator=(const Cd & d); // 没有动态分配不用写就浅复制足够了 }; class Classic : public Cd { char master [50]; public: // Classic(const Classic &d); Classic(char *mt,char *s1, char *s2, int n,double x); Classic(){}; // Classic(char *mt,const Cd &d); // 没用到 virtual void Report() const; // Cd &operator=(const Cd & d); }; #endif /* jaycd_hpp */.cpp
#include "jaycd.hpp" #include <iostream> #include <string> using namespace std; Cd::Cd(){} // Cd::Cd(const Cd &d){} Cd::Cd(char *s1, char *s2, int n,double x) { strncpy(performers, s1, 50); strncpy(label, s2, 20); selections = n; playtime = x; } Cd::~Cd(){} void Cd::Report() const { cout << "performers: " << performers <<endl; cout << "label: " << label <<endl; cout << "selections: " << selections <<endl; cout << "playtime: " << playtime <<endl; } // Cd &operator=(const Cd & d){} Classic::Classic(char *mt,char *s1, char *s2, int n,double x) : Cd(s1,s2,n,x) { strncpy(master, mt, 50); } void Classic::Report() const { Cd::Report(); cout << "master: " << master <<endl; }main函数不变 .hpp
#ifndef jaycd_hpp #define jaycd_hpp #include <stdio.h> class Cd{ private: char * performers; // 表演者 char * label; // 标签 int selections; // 选集 double playtime; // 播放时间 public: Cd(); Cd(const Cd &d); Cd(char *s1, char *s2, int n,double x); virtual ~Cd(); virtual void Report() const; Cd &operator=(const Cd & d); }; class Classic : public Cd { char *master; public: Classic(const Classic &d); Classic(char *mt,char *s1, char *s2, int n,double x); Classic(); //Classic(char *mt,const Cd &d); // 没用到 virtual void Report() const; Classic & operator=(const Classic & d); virtual ~Classic(); }; #endif /* jaycd_hpp */.cpp
#include "jaycd.hpp" #include <iostream> #include <string> using namespace std; Cd::Cd() { performers = nullptr; label = nullptr; } Cd::Cd(const Cd &d) { performers = new char[strlen(d.performers) + 1]; label = new char[strlen(d.label) + 1]; // 分配内存 strcpy(performers, d.performers); strcpy(label, d.label); selections = d.selections; playtime = d.playtime; } Cd::Cd(char *s1, char *s2, int n,double x) { performers = new char[strlen(s1) + 1]; label = new char[strlen(s2) + 1]; // 分配内存 strcpy(performers, s1); strcpy(label, s2); selections = n; playtime = x; } Cd::~Cd(){ // delete delete [] performers; delete [] label; } void Cd::Report() const { cout << "performers: " << performers <<endl; cout << "label: " << label <<endl; cout << "selections: " << selections <<endl; cout << "playtime: " << playtime <<endl; } Cd & Cd::operator=(const Cd & d){ if(this == &d) return *this; delete [] performers; delete [] label; performers = new char[strlen(d.performers) + 1]; label = new char[strlen(d.label) + 1]; // 分配内存 strcpy(performers, d.performers); strcpy(label, d.label); selections = d.selections; playtime = d.playtime; return *this; } Classic::Classic(char *mt,char *s1, char *s2, int n,double x) : Cd(s1,s2,n,x) { master = new char[strlen(mt) + 1]; strcpy(master, mt); } void Classic::Report() const { Cd::Report(); cout << "master: " << master <<endl; } Classic::Classic(const Classic &d):Cd(d) { master = new char[strlen(d.master) + 1]; strcpy(master, d.master); } Classic::Classic():Cd() { master = nullptr; } Classic & Classic::operator=(const Classic & d) { if(this == &d) return *this; Cd::operator=(d); master = new char[strlen(d.master) + 1]; strcpy(master, d.master); return *this; } Classic::~Classic() { delete [] master; }在main函数中可以看到创建空对象:
Classic copy;所以我们要写上构造函数,因为我们已经自己写了构造函数,系统将不再给我们默认构造函数。
Cd::Cd() { performers = nullptr; label = nullptr; } Classic::Classic():Cd() { master = nullptr; }第三题偷懒咯,向第四题出发
.hpp
#ifndef Port_hpp #define Port_hpp #include <stdio.h> #include <iostream> using namespace std; class Port { private: char * brand; // 品牌 char style[20]; // 酒的品种 int bottles; // 瓶数 public: Port(const char * br = "none", const char *st = "none", int b = 0); Port(const Port & p); virtual ~Port(){delete [] brand;} Port & operator=(const Port & p); Port & operator+=(int b); Port & operator-=(int b); int BottleCount() const {return bottles;} virtual void Show() const; friend ostream & operator<<(ostream & os, const Port &p); }; class VintagePort : public Port { private: char * nickname; int year; public: VintagePort(const char * br, int b, const char * nn, int y); VintagePort(const VintagePort &vp); ~VintagePort(){delete [] nickname;} VintagePort & operator=(const VintagePort &vp); void Show() const; friend ostream & operator<<(ostream & os, const VintagePort &p); }; #endif /* Port_hpp */.cpp
#include "Port.hpp" #include <iostream> #include <string> using namespace std; Port::Port(const char * br, const char *st, int b) { brand = new char[strlen(br) + 1]; strcpy(brand, br); strncpy(style, st, 20); bottles = b; } Port::Port(const Port & p) { // 复制构造函数 brand = new char[strlen(p.brand) + 1]; strcpy(brand, p.brand); strncpy(style, p.style, 20); bottles = p.bottles; } Port & Port::operator=(const Port & p) { if(this == &p) return *this; delete [] brand; brand = new char[strlen(p.brand) + 1]; strcpy(brand, p.brand); strncpy(style, p.style, 20); bottles = p.bottles; return *this; } Port & Port::operator+=(int b) { bottles += b; return *this; } Port & Port::operator-=(int b) { bottles -= b; return *this; } void Port::Show() const { cout << "brand: " << brand <<endl; cout << "style: " << style <<endl; cout << "bottles: " << bottles <<endl; } ostream & operator<<(ostream & os, const Port &p) { os << p.brand << ", " << p.style << ", " << p.bottles; return os; } VintagePort::VintagePort(const char * br, int b, const char * nn, int y) :Port(br, "Vintage", b) { nickname = new char[strlen(nn) + 1]; strcpy(nickname, nn); year = y; } VintagePort::VintagePort(const VintagePort &vp):Port(vp) { nickname = new char[strlen(vp.nickname) + 1]; strcpy(nickname, vp.nickname); year = vp.year; } VintagePort & VintagePort::operator=(const VintagePort &vp) { if(this == &vp) return *this; delete [] nickname; Port::operator=(vp); nickname = new char[strlen(vp.nickname) + 1]; strcpy(nickname, vp.nickname); year = vp.year; return *this; } void VintagePort::Show() const { Port::Show(); cout << "Nickname: " << nickname << endl; cout << "Year: " << year << endl; } ostream & operator<<(ostream & os, const VintagePort & vp) { os << Port(vp); os << ", " << vp.nickname << ", " << vp.year; return os; }这个代码复习了下上节课学的 友元函数无法指定哪个类,所以强制类型转换,其他没什么好说的了