首页 > 解决方案 > 如何使基类的方法使用派生类集的继承的受保护成员?C++

问题描述

我有一个问题,即使循环中的代码具有正确的指针类型(如对显示的调用) ,如果我没记错的话,tells()它仍然使用getPointer()默认构造的类。Triangle如何调用getPointer()循环返回指向保存坐标的内存的指针?

主.cpp:

#include <triangles.h>
#include <memory>
#include<QVector>
class C {
public:
    std::shared_ptr<Triangle> shp;
};

int main() {
    QVector<C> vc;
    C t, a, b;
    t.shp = std::make_shared<Triangle>(10,20,30,40,50,60);
    a.shp = std::make_shared<EqualTriangle>(10,20, 53);
    b.shp = std::make_shared<IsoscelesTriangle>(10,20, 53, 152);
    vc.push_back(t);
    vc.push_back(a);
    vc.push_back(b);
    for(auto x: vc) {
        const QPointF * p = x.shp->getPointer();
        x.shp->tell();
        qDebug() << (void*) p;
        qDebug() << p[0]<< p[1]<<p[2];
    }
    return 0;
}

三角形.h:

#define TRIANGES_H
#include<QPointF>
#include<cmath>
#include<QDebug>
class Triangle
{
public:
    Triangle() = default;
    Triangle(float ax, float ay, float bx, float by, float cx, float cy);
    Triangle(QPointF a, QPointF b, QPointF c);
    const QPointF *getPointer() {qDebug() << "triangle getpoint called"; return points; }
    virtual void tell() { qDebug()<<"triangle tells";}

protected:
    QPointF points[3];
};

class IsoscelesTriangle : public Triangle
{
public:
    IsoscelesTriangle() = default;
    IsoscelesTriangle(QPointF point, uint side_len, uint base_len);
    IsoscelesTriangle(float px, float py, uint side_len, uint base_len ): Triangle() {
        IsoscelesTriangle(QPointF(px, py), side_len, base_len);
    virtual void tell() { qDebug()<<"iso triangle tells";}

};

class EqualTriangle : public IsoscelesTriangle
{
public:
    EqualTriangle() = default;
    EqualTriangle(QPointF point, uint side_len ):IsoscelesTriangle() { IsoscelesTriangle(point, side_len, side_len);}
    EqualTriangle(float px, float py, uint side_len) :IsoscelesTriangle() {
        EqualTriangle(QPointF(px,py), side_len);
    }
    virtual void tell() { qDebug()<<"equal triangle tells";}

};

#endif // TRIANGES_H

三角形.cpp:

#include "triangles.h"
#include <QDebug>

Triangle::Triangle(float ax, float ay, float bx, float by, float cx, float cy)
{
    points[0] = QPointF(ax, ay);
    points[1] = QPointF(bx, by);
    points[2] = QPointF(cx, cy);
}

Triangle::Triangle(QPointF a, QPointF b, QPointF c)
{
    points[0] = a;
    points[1] = b;
    points[2] = c;
}

IsoscelesTriangle::IsoscelesTriangle(QPointF point, uint side_len, uint base_len) : Triangle()
{
    points[0] = point;
    points[1] = QPointF(point.x()+base_len, point.y());
    points[2] = QPointF(point.x()+base_len/2, point.y() +sqrt(side_len*side_len - (base_len*base_len)/4));
}

输出:

triangle getpoint called
triangle tells
0x560340e8fd38
QPointF(10,20) QPointF(30,40) QPointF(50,60)
triangle getpoint called
equal triangle tells
0x560340e8fd88
QPointF(0,0) QPointF(0,0) QPointF(0,0)
triangle getpoint called
iso triangle tells
0x560340e8fdd8
QPointF(0,0) QPointF(0,0) QPointF(0,0) 

标签: c++oopinheritanceprotected

解决方案


这段代码中的主要问题是,当派生类的构造函数(除了此处未使用的之外的所有IsoscelesTriangle(QPointF ,uint, uint)构造函数都被调用)时,它们会在自身内部调用其他构造函数,从而创建一个临时对象而不是初始化类字段。

此外,为封装起见points,创建基类的私有成员并在基类中创建受保护的成员函数也是一个好主意。void setPoints(QPointF a, QPointF b, QPointF c)

固定构造函数看起来像这样:

三角形.cpp


IsoscelesTriangle::IsoscelesTriangle(QPointF point, uint side_len, uint base_len)
{
    QPointF a = point;
    QPointF b = QPointF(point.x()+base_len, point.y());
    QPointF c = QPointF(point.x()+base_len/2, point.y() +sqrt(side_len*side_len - (base_len*base_len)/4));
    setPoints(a,b,c);
}

三角形.h

    IsoscelesTriangle(float a, float b, uint side_len, uint base_len):IsoscelesTriangle(QPointF(a,b), side_len, base_len) {}
    EqualTriangle(QPointF point, uint side_len ): IsoscelesTriangle(point, side_len, side_len) { }
    EqualTriangle(float x, float y, uint side_len ): IsoscelesTriangle(QPointF(x,y), side_len, side_len) { }

推荐阅读