c语言中的类和继承复习
实现一个简单的猫咪🐈类:
c1.h:
运行下面代码
#include <iostream> using namespace std; class Cat{ public: Cat(int intialAge); ~Cat(); int getAge() const { return itsAge; } void setAge(int age) { itsAge = age; } void Meow() const { cout << "Meow \n"; } private: int itsAge; };
c1.cpp
运行下面代码
#include "c1.h" Cat::Cat(int initialAge) { itsAge = initialAge; } Cat::~Cat() {} int main() { Cat c(5); c.Meow(); c.setAge(8); cout << "now age is " << c.getAge() << endl; return 0; }
类的继承和派生:
实现一个父类Mammal, 让Dog继承这个父类:
运行下面代码
#include <iostream> using namespace std; enum BREED{GOLDEN, DANDIE, LAB}; class Mammal{ public: Mammal(){}; ~Mammal(){}; //访问器和设置器; int getAge() const { return itsAge; }; void setAge(); int getWeight() const { return itsWeight; }; void setWeight(); //其它方法; void speak() const { cout<<"Mammal sound\n"; }; void sleep() const { cout<<"Mammal.zZzZ.."; }; protected: int itsAge; int itsWeight; }; // class Dog : public Mammal{ public: //初始化狗狗类型 Dog():itsBreed(GOLDEN){ }; ~Dog(){}; BREED getBreed() const { return itsBreed; } void setBreed(BREED breed) { itsBreed = breed; } //其它方法 void wagTail() const { cout<<"wag tail \n"; } void begForFood() const{ cout<<"begging for food \n"; } private: BREED itsBreed; }; int main() { Dog d; d.wagTail(); d.begForFood(); cout << " the breed of dog is "; cout << d.getBreed(); cout << endl; return 0; }
通过继承实现一只小狗🐶 :
运行下面代码
#include <iostream> using namespace std; enum BREED{GOLDEN, DANDIE, LAB}; class Mammal{ public: Mammal(); Mammal(int age); ~Mammal(){}; //访问器和设置器; int getAge() const { return itsAge; }; void setAge(); int getWeight() const { return itsWeight; }; void setWeight(); //其它方法; void speak() const { cout<<"Mammal sound\n"; }; void sleep() const { cout<<"Mammal.zZzZ.."; }; protected: int itsAge; int itsWeight; }; class Dog : public Mammal{ public: Dog(); Dog(int age); Dog(int age , int weight); Dog(int age, int weight, BREED breed); BREED getBreed() const { return itsBreed; } void setBreed(BREED breed) { itsBreed = breed; } //其它方法 void wagTail() const { cout << "wag tail \n"; } void begForFood() const{ cout << "begging for food \n"; } void show() { cout << itsAge << "\n"; cout << itsWeight << "\n"; cout << itsBreed << "\n"; } private: BREED itsBreed; int itsAge; int itsWeight; }; Mammal::Mammal():itsAge(1),itsWeight(1) { cout << "MaMMal constructor" << endl; } Mammal::Mammal(int age): itsAge(age), itsWeight(5) { cout << "MaMMal constructor " << endl; } Dog::Dog(){} Dog::Dog(int age):itsAge(age){} Dog::Dog(int age, int weight):itsAge(age),itsWeight(weight){} Dog::Dog(int age, int weight, BREED breed):itsAge(age),itsWeight(weight),itsBreed(breed){} int main() { Dog d(2,2,GOLDEN); d.show(); return 0; }
使用继承的时候要注意,如果子类使用继承覆盖了父类的一个方法, 父类的其它同名的方法也要覆盖, 如果不希望它们被隐藏, 必须对其进行覆盖:
运行下面代码
#include <iostream> using namespace std; class Mammal{ public: Mammal(); ~Mammal(){}; //其它方法; void speak() const { cout << "Mammal sound\n"; }; void sleep() const { cout << "Mammal.zZzZ.."; }; void move() const { cout << "mammal move one step\n"; } void move(int st) const { cout << "mammal move "<< st <<" step\n"; } }; class Dog : public Mammal{ public: Dog(); ~Dog(){}; //其它方法 void wagTail() const { cout << "wag tail \n"; } void begForFood() const{ cout << "begging for food \n"; } void move() const { cout << "dog move two step\n"; } }; Mammal::Mammal(){} Dog::Dog(){} int main() { Mammal m; Dog d; m.move(); d.move(); m.move(2); //这一句报错了, 因为Dog没有重载Mammal的move( int step)方法 //d.move(2); return 0; }
子类要调用父类的相关方法,有两种调用方式,
第一种是:子类.父类方法();
第二种是:子类.父级构造函数::父级方法():
运行下面代码
#include <iostream> using namespace std; class Mammal{ public: Mammal(); ~Mammal(){}; //其它方法; void speak() const { cout << "Mammal sound\n"; }; void sleep() const { cout << "Mammal.zZzZ..\n"; }; }; class Dog : public Mammal{ public: Dog(); ~Dog(){}; //其它方法 void wagTail() const { cout << "wag tail \n"; } void begForFood() const{ cout << "begging for food \n"; } }; Mammal::Mammal(){} Dog::Dog(){} int main() { Dog d; d.sleep(); //第一种调用方式 d.Mammal::sleep(); //第二种调用方式 return 0; }
虚拟函数:
如果我创建了一个子类对象, 对象的指针却指向了父类, 问题来了, 我要调用这个实例的方法, 会执行父类的方法,还说子类的方法呢:
运行下面代码
#include <iostream> using namespace std; class Mammal{ public: Mammal(); ~Mammal(){}; //其它方法; void speak() const { cout << "Mammal sound\n"; }; void sleep() const { cout << "Mammal.zZzZ..\n"; }; }; class Dog : public Mammal{ public: Dog(); ~Dog(){}; //其它方法 void speak() const { cout << "Dog sound\n"; }; void sleep() const { cout << "Dog.zZzZ..\n"; }; }; Mammal::Mammal(){} Dog::Dog(){} int main() {; Dog d; d.speak(); d.sleep(); Mammal * m = new Dog(); m->speak(); m->sleep(); return 0; }
实际上指针是啥类型的, 那么就会调用对应构造函数下的方法;
虚方法的作用就会体现出来,无论指针是指向父类还是子类, 只要确定创建实例的构造函数是哪一个,那么就会调用对应构造函数下的方法,
在父类的构造方法上添加virtual关键字, virtual是可以继承的, 只要父类写了一个virtual, 会自动继承到子类去:
运行下面代码
#include <iostream> using namespace std; class Mammal{ public: Mammal(); ~Mammal(){}; //其它方法; virtual void speak() const { cout << "Mammal sound\n"; }; virtual void sleep() const { cout << "Mammal.zZzZ..\n"; }; }; class Dog : public Mammal{ public: Dog(); ~Dog(){}; //其它方法 void speak() const { cout << "Dog sound\n"; }; void sleep() const { cout << "Dog.zZzZ..\n"; }; }; Mammal::Mammal(){} Dog::Dog(){} int main() {; Dog d; d.speak(); d.sleep(); Mammal * m = new Dog(); m->speak(); m->sleep(); return 0; }
虚函数有啥用呢
运行下面代码
#include <iostream> using namespace std; class Mammal{ public: Mammal(){}; ~Mammal(){}; virtual void sleep() const { cout << "Mammal.zZzZ..\n"; }; }; class Dog : public Mammal{ public: Dog(){}; ~Dog(){}; void sleep() const { cout << "Dog.zZzZ..\n"; }; }; class Bird : public Mammal{ public: Bird(){}; ~Bird(){}; void sleep() const { cout << "Bird.zZzZ..\n"; }; }; int main() { Mammal* arr[3]; int i; for(i=0; i<3; i++) { Mammal* m; switch(i) { case 0: m = new Mammal(); break; case 1: m = new Dog(); break; case 2: m = new Bird(); break; } arr[i] = m; } for(i=0; i<3; i++) { arr[i]->sleep(); } return 0; }
只要定义一种数据类型的数组, 数组中的元素全部为子类;
虚函数耶可以作为纯接口函数使用, 子类负责实现:
运行下面代码
#include <iostream> using namespace std; class Animal{ public: virtual void eat() = 0; }; class Cat:public Animal{ public: void eat() { cout << "eat it ....ing" << endl; } }; int main() { Cat c; c.eat();//eat it ....ing return 0; }
以下一个案例要了解一下, 当使用虚函数的时候, 如果把子类强转为父类型, 那么就会损失子类定义的方法和属性:
运行下面代码
#include <iostream> using namespace std; class Mammal{ public: Mammal(){}; ~Mammal(){}; virtual void sleep() const { cout << "Mammal.zZzZ..\n"; }; }; class Dog : public Mammal{ public: Dog(){}; ~Dog(){}; void sleep() const { cout << "Dog.zZzZ..\n"; }; }; class Bird : public Mammal{ public: Bird(){}; ~Bird(){}; void sleep() const { cout << "Bird.zZzZ..\n"; }; }; void refFn(Mammal& m) { m.sleep(); } void ptrFn(Mammal* m) { m->sleep(); } void slice(Mammal m) { m.sleep(); } int main() { Mammal* arr[3]; int i; for(i=0; i<3; i++) { Mammal* m; switch(i) { case 0: m = new Mammal(); break; case 1: m = new Dog(); break; case 2: m = new Bird(); break; } arr[i] = m; } for(i=0; i<3; i++) { //refFn(*arr[i]); //ptrFn(arr[i]); slice(*arr[i]); } return 0; }
私有继承的方法和属性无法直接访问,只能通过子类的方法访问, 注意下面的private关键字:
运行下面代码
#include <iostream> using namespace std; //私有继承 class Elec{ public: Elec() {}; void start() { cout << "start ....ing" << endl; } void stop() { cout << "stop ....ing" << endl; } }; class Fan : private Elec{ public: void run() { start(); } void unRun() { stop(); } }; int main() { Fan f; f.run(); f.unRun(); //因为使用的是私有继承, 所以无法调用f的start和stop方法; //f.start(); //f.stop(); return 0; }
如果不使用继承,通过组合也可以实现效果:
运行下面代码
#include <iostream> using namespace std; //私有继承 class Elec{ public: Elec() {}; void start() { cout << "start ....ing" << endl; } void stop() { cout << "stop ....ing" << endl; } }; class Fan{ private: Elec elec; public: void run() { elec.start(); } void unRun() { elec.stop(); } }; int main() { //组合的方式实现继承; Fan f; f.run(); f.unRun(); return 0; }
算术运算符的重载, 重载+号:
运行下面代码
#include <iostream> using namespace std; //重载算术运算符 class Date{ public: Date(); ~Date(){}; Date operator+ (int i) { cout << "nice gay" << endl; cout << i << endl; return *this; } }; Date::Date(){}; int main() { Date date; date+10; return 0; }
重载++运算符:
运行下面代码
#include <iostream> using namespace std; //重载算术运算符 class Date{ private: int day; public: Date(); ~Date(){}; Date operator++ () { day++; return *this; } int getDay() { return day; } }; Date::Date():day(0){}; int main() { Date date; ++date; ++date; cout << "now is " << date.getDay() << endl; return 0; }
通过使用智能指针, 可以实现自动释放申请到的内存:
运行下面代码
#include <iostream> using namespace std; class Dog{ public: Dog() { } ~Dog() { cout << "destructor Dog" << endl; } void bark() { cout << "bark.wa.wa.wa" << endl; } }; int main() { auto_ptr <int> p (new int); *p = 21; cout << *p <<endl; auto_ptr <Dog> pd (new Dog); pd->bark(); return 0; }
可以通过一些重载方法,让实例对象转换为数字, 或者让对象转换为字符串:
运行下面代码
#include <iostream> class Dog{ public: operator int() { return 100; } operator std::string() { return "abcd"; } }; int main() { Dog dg; int index = dg; std::cout << "index is " << dg << std::endl; std::string str(dg); std::cout << "string is " << str << std::endl; return 0; }
在说智能指针之前,有必要复习一下,模版(泛型)的创建, 泛型的实例化:
运行下面代码
#include <iostream> using namespace std; template<typename T> class Dog{ private: T i; public: Dog(T _i) { i = _i; } ~Dog() { cout << "destructor Dog" << endl; } void bark() { cout << "my xx is " << i << endl; } }; int main() { Dog<int> d(1); d.bark(); Dog<char> dd('a'); dd.bark(); return 0; }
如何去实现一个智能指针, 有了智能指针,就可以防止申请了内存, 又忘记清空:
运行下面代码
#include <iostream> template <typename T> class smart_pointer{ private: T* ptr; public: smart_pointer(T* p):ptr(p){}; ~smart_pointer() { delete ptr; } //smart_pointer& operator=(const smart_pointer& anotherPtr); T& operator*() { return *ptr; } T* operator->() { return ptr; } }; using namespace std; class Dog{ public: Dog() { } ~Dog() { cout << "destructor Dog" << endl; } void bark() { cout << "bark.wa.wa.wa" << endl; } }; int main() { //这两种写法都可以 // smart_pointer<Dog> p = new Dog(); smart_pointer<Dog> p(new Dog); p->bark(); // Dog* d = new Dog(); // d->bark(); return 0; }
模版关键字:
运行下面代码
#include <stdio.h> template<typename T> void swap(T & t, T & t1) { T tmp = t; t = t1; t1 = tmp; return ; } int main() { int i = 1; int j = 2; swap<int>(i, j); printf("%d, %d",i, j); // cout << i << endl; // cout << j << endl; return 0; }
模版关键字实现一个固定长度的数组:
运行下面代码
#include <stdio.h> #include <iostream> template<class T> class Array { public: Array(); ~Array(); void push(const T& t); T pop(); private: int maxSize; int nowIndex; T* newData; }; template<class T>Array<T>::Array():maxSize(100), nowIndex(0) { newData = new T[maxSize]; std::cout << "new T" << std::endl; } template<class T>Array<T>::~Array() { delete newData; std::cout << "destructing" << std::endl; } template<class T>void Array<T>::push(const T& t) { newData[nowIndex] = t; nowIndex = ++nowIndex>=maxSize ? maxSize : nowIndex; } template<class T>T Array<T>::pop() { nowIndex = nowIndex-- >=0 ? nowIndex : 0; return newData[nowIndex]; } int main() { Array<int> array; array.push(100); array.push(2); std::cout << array.pop()+array.pop() << std::endl; return 0; }
以上代码的简化版:
运行下面代码
#include <stdio.h> #include <iostream> template<class T> class Array { public: Array():maxSize(100), nowIndex(0) { newData = new T[maxSize]; std::cout << "new T" << std::endl; } ~Array() { delete newData; std::cout << "destructing" << std::endl; } void push(const T& t) { newData[nowIndex] = t; nowIndex = ++nowIndex>=maxSize ? maxSize : nowIndex; } T pop() { nowIndex = nowIndex-- >=0 ? nowIndex : 0; return newData[nowIndex]; } private: int maxSize; int nowIndex; T* newData; }; int main() { Array<int> array; array.push(100); array.push(2); std::cout << array.pop()+array.pop() << std::endl; return 0; }
eof
eof
本文作者:方方和圆圆
本文链接:https://www.cnblogs.com/diligenceday/p/6046605.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步