本文共 8849 字,大约阅读时间需要 29 分钟。
在C++编程中,继承是面向对象编程的核心概念之一。通过继承,一个新类可以基于已有的类(基类)继承其属性和方法,从而避免重复代码并增强代码的可维护性。本文将通过多个代码示例,探讨C++继承的不同方面及其常见错误。
以下代码展示了一个简单的基类及其派生类:
class Base {public: Base() {} Base(int i) : b_number(i) {} int get_number() { return b_number; } void print() { cout << b_number << endl; }};class Derived : public Base {private: int d_number;public: Derived(int i, int j) : Base(i), d_number(j) {} void print() { cout << get_number() << " "; cout << d_number << endl; }};int main() { Base a(2); Derived b(3, 4); cout << "a is "; a.print(); cout << "b is "; b.print(); cout << "base part of b is "; b.Base::print(); return 0;}
错误分析:
Derived
中,print()
方法没有正确调用基类Base
的print()
方法,导致无法正确显示基类属性。Base::print()
时,派生类的成员函数没有被正确隐藏,可能导致重复调用。优化建议:
print()
方法中,先调用基类的print()
方法,然后显示派生类的属性。b.Base::print()
时,应确保派生类对象可以正确访问基类的成员。以下代码展示了使用虚基类实现多态的示例:
class Thing {public: virtual void what_Am_I() { cout << "I am a Thing.\n"; } ~Thing() { cout << "Thing destructor\n"; }};class Animal : public Thing {public: virtual void what_Am_I() { cout << "I am an Animal.\n"; } ~Animal() { cout << "Animal destructor\n"; }};int main() { Thing *t = new Thing; Animal *x = new Animal; Thing *array[2] = {t, x}; for (int i = 0; i < 2; ++i) array[i]->what_Am_I(); delete[] array; return 0;}
错误分析:
virtual
关键字标记what_Am_I()
和析构函数,导致无法实现多态和内存泄漏。优化建议:
Thing
中声明what_Am_I()
和~Thing()
为虚函数。Animal
中重写what_Am_I()
和~Animal()
,确保正确实现多态。以下代码展示了多级继承及纯虚函数的应用:
class Figure {public: virtual void draw() = 0; virtual void rotate(double) = 0; Point &location() { return center; } void move(Point p) { center = p; } virtual ~Figure() {}};class Circle : public Figure {public: Circle(double r = 0, double x = 0, double y = 0) : Figure(x, y), radius(r) {} void draw() { cout << "A circle with center "; location().print(); cout << " and radius " << radius << endl; } void rotate(double) { cout << "no effect.\n"; } ~Circle() {}};class Square : public Figure {public: Square(double x = 0, double y = 0, double d = 0, double a = 0) : Figure(x, y), side(d), angle(a) {} void draw() { cout << "A square with center "; location().print(); cout << " side length " << side << "\n"; } void rotate(double a) { angle += a; cout << "The angle between one side and the X-axis is " << angle << endl; } ~Square() {}};int main() { Circle c(3); Square s(4, 5, 6); Figure *f = &c; f->draw(); f->move(Point(2, 2)); s.draw(); s.rotate(1); return 0;}
错误分析:
Circle
和Square
类没有正确实现纯虚函数rotate()
,导致无法实现多态。override
关键字标记重写的虚函数,可能导致编译错误。优化建议:
override
关键字标记重写的虚函数。以下代码展示了私有继承及访问控制的应用:
class Base {private: int priv;protected: int prot;public: int publ; Base() {} Base(int a, int b, int c) : priv(a), prot(b), publ(c) {} int get_priv() { return priv; } int get_prot() { return prot; } int get_publ() { return publ; }};class Derived1 : private Base {public: Derived1(int a, int b, int c) : Base(a, b, c) {} int get1_priv() { return get_priv(); } int get1_prot() { return prot; } int get1_publ() { return publ; }};class Leaf1 : public Derived1 {public: Leaf1(int a, int b, int c) : Derived1(a, b, c) {} void print() { cout << "Leaf1 members: " << get1_priv() << " " << get1_prot() << " " << get1_publ() << endl; }};int main() { Derived1 d1(1, 2, 3); Leaf1 lf1(4, 5, 6); cout << lf1.get1_priv() << " " << lf1.get1_prot() << " " << lf1.get1_publ() << endl; return 0;}
错误分析:
Leaf1
中,print()
方法试图访问基类的get_priv()
和get_prot()
方法,但由于私有继承,不能直接访问。优化建议:
Base::get_priv()
和Base::get_prot()
访问基类的成员函数。以下代码展示了多级继承及多态的应用:
class Point {public: Point(double x = 0, double y = 0) { x = xval; y = yval; }protected: double x, y;};class Circle : public Point {public: Circle(double r = 0, double xval = 0, double yval = 0) : Point(xval, yval), radius(r) {} double area() { return 3.14159 * radius * radius; }protected: double radius;};class Cylinder : public Circle {public: Cylinder(double hv = 0, double rv = 0, double xv = 0, double yv = 0) : Circle(xv, yv, rv), height(hv) {} double area() { return 2.0 * Circle::area() + 2.0 * 3.14159 * radius * height; }protected: double height;};int main() { Point p(2, 3); Circle c(7, 6, 5); Cylinder cyl(10, 11, 12, 13); cout << p; cout << c; cout << "area of circle: " << c.area() << endl; cout << cyl; cout << "area of cylinder: " << cyl.area() << endl; return 0;}
错误分析:
Cylinder
类的area()
函数没有正确使用Circle::area()
,导致错误。Cylinder
类没有正确初始化radius
和height
成员变量。优化建议:
Cylinder
类的构造函数中,确保正确初始化radius
和height
。area()
函数中,正确调用Circle::area()
。以下代码展示了protected访问控制属性的应用:
class Point {public: Point(double xval = 0, double yval = 0) { x = xval; y = yval; }public: void print() { cout << " Point:X:Y: " << x << "," << y << "/n"; }protected: double x, y;};class Circle : public Point {public: Circle(double r = 0, double xval = 0, double yval = 0) : Point(xval, yval), radius(r) {} void print() { cout << "Circle:radius:" << radius << endl; } double area() { return 3.14159 * radius * radius; }protected: double radius;};int main() { Point p(2, 3); Point pp = p; Circle c(7, 6, 5); cout << "Point P= " << p; cout << "Point PP= " << pp; cout << "Circle c= " << c; pp = c; cout << "Point PP= " << pp; pp = (Point)c; cout << "Point PP= " << pp; return 0;}
错误分析:
Circle
类的print()
方法试图访问Point
类的成员x
和y
,但由于protected
属性,无法直接访问。优化建议:
Point::x
和Point::y
访问基类成员。以下代码展示了类的兼容性规则:
class Base {public: void func() { cout << "Base class function.\n"; }};class Derived : public Base {public: void func() { cout << "Derived class function.\n"; }};void foo(Base b) { b.func(); }int main() { Derived d; Base b; Base *p = &d; Base br = d; b = d; b.func(); d.func(); p->func(); foo(d); br.func(); return 0;}
错误分析:
p->func()
和br.func()
没有问题,但b = d
可能导致错误,因为Derived
没有构造基类成员。优化建议:
Derived
的构造函数中,确保正确初始化基类成员。b = d
,除非Derived
有正确的构造函数。以下代码展示了虚析构函数的应用:
class Base {private: int id; char *name;public: Base(int a = 0, char *s = "") : id(a) { if (!s) name = NULL; else { name = new char[strlen(s) + 1]; strcpy(name, s); } cout << "base default constructor\n"; } Base(const Base &b) : id(b.id) { if (!b.name) name = NULL; else { name = new char[strlen(b.name) + 1]; strcpy(name, b.name); } cout << "base copy constructor\n"; } ~Base() { if (name != NULL) delete[] name; cout << "base destructor\n"; } const Base &operator=(const Base &b) { if (this != &b) { id = b.id; delete[] name; if (!b.name) name = NULL; else { name = new char[strlen(b.name) + 1]; strcpy(name, b.name); } } cout << "base assignment operator\n"; return *this; } friend ostream &operator<<(ostream &out, const Base &b) { out << "Base member id = " << b.id << endl; out << "Base member name = " << b.name << endl; return out; }};class Derived : public Base {private: float f; char *label;public: Derived(int a = 0, char *s = "", float x = 0, char *t = "") : Base(a, s), f(x) { if (!t) label = NULL; else { label = new char[strlen(t) + 1]; strcpy(label, t); } cout << "derived default constructor\n"; } Derived(const Derived &d) : Base(d), f(d.f) { if (!d.label) label = NULL; else { label = new char[strlen(d.label) + 1]; strcpy(label, d.label); } cout << "derived copy constructor\n"; } ~Derived() { delete[] label; cout << "derived destructor\n"; } const Derived &operator=(const Derived &d) { if (this != &d) { Base::operator=(d); f = d.f; if (!d.label) label = NULL; else { label = new char[strlen(d.label) + 1]; strcpy(label, d.label); } } cout << "derived assignment operator\n"; return *this; } friend ostream &operator<<(ostream &out, const Derived &d) { out << (Base)d; out << "Derived member f = " << d.f << endl; out << "Derived member label = " << d.label << endl; return out; }};int main() { Derived d1; Derived d2(d1); return 0;}
错误分析:
Derived
类的operator=
方法没有正确初始化label
成员,可能导致内存泄漏。override
关键字标记重写的虚函数,导致编译错误。优化建议:
Derived
的构造函数中,确保正确初始化label
成员。override
关键字标记重写的虚函数。label
的内存释放。通过以上分析和优化,可以更好地理解C++继承的思想及其在实际编程中的应用。
转载地址:http://zquwz.baihongyu.com/