简体   繁体   中英

How to make method of a base class use inherited protected members that derived class sets? C++

I've got a problem that even though the code in the loop has the correct pointer type ( as call to tells() shows ) it still uses getPointer() over default constructed Triangle class, if I'm not wrong. How to make a call to getPointer() in loop return a pointer to the memory where the coordinates saved?

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

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

Output:

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) 

The main problem in this code is that when constructors of derived classes (all but the unused here IsoscelesTriangle(QPointF,uint, uint) are called they invoke additional constructors inside themselves thus creating a temporary object instead of initializing class fields.

Also it would be a good idea to make points a private member of a base class and create a protected member function void setPoints(QPointF a, QPointF b, QPointF c) in base class for encapsulation's sake.

Fixed constructors would look like that:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM