Как заставить метод базового класса использовать унаследованные защищенные члены, которые устанавливают производные классы? C ++ - PullRequest
0 голосов
/ 06 мая 2020

У меня проблема в том, что, хотя код в l oop имеет правильный тип указателя (как показывает вызов tells()), он по-прежнему использует getPointer() вместо созданного по умолчанию класса Triangle, если я я не ошибаюсь. Как сделать вызов getPointer() в l oop вернуть указатель на память, где сохранены координаты?

main. 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;
}

triangles.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) 

1 Ответ

0 голосов
/ 06 мая 2020

Основная проблема в этом коде заключается в том, что при вызове конструкторов производных классов (все, кроме неиспользуемых здесь 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);
}

triangles.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) { }
...