I am trying to make all my classes to be generic.But the issue arose with class Circle and the ones following right after it.Where am I making a mistake?
It seems to work when I exchange them for "int". But that seems to fail my original needs of having the classes be generic.
class DrawableObject
{
public:
virtual void print()=0;
};
template <typename T>
class Point : public DrawableObject
{
T x;T y;
public:
Point()
{ x=0;
y=0;
}
Point(T a)
{ x=a;
y=a;
}
Point(T a,T b)
{ x=a;
y=b;
}
void setX(T newX)
{
x=newX;
}
void setY(T newY)
{
y=newY;
}
T getX()
{ return x;
}
T getY()
{ return y;}
void print()
{ cout<<"(X,Y) Coordinates are ("<<x<<","<<y<<")"<<endl;}
};
template <typename U>
class Rectangle : public Point<U>
{
U width,height;
public:
Rectangle()
{ width=0;
height=0;
}
Rectangle(U a)
{ width=a;
height=a;
}
Rectangle(U a,U b)
{ width=a;
height=b;
}
void setWidth(U newWidth)
{ width=newWidth;}
void setHeight(U newHeight)
{ height=newHeight;}
U getHeight()
{ return height;}
U getWidth()
{ return width;}
void print()
{ cout<<"Rectangle is of area "<<width<<"X"<<height<<endl;}
};
Issue arises from here onwards
template <typename V>
class Circle : public Point<V>
{
V radius;
public:
Circle():Point()
{
radius=0;
}
Circle(V a):Point(a)
{
radius=a;
}
Circle(V a,V b,V c):Point(a,b)
{
radius=c;
}
void setRadius(V newRadius)
{radius=newRadius;}
V getRadius()
{return radius;}
void print()
{cout<<"Circle with centre at ("<<getX()<<","<<getY()<<") and of radius "<<radius<<endl;}
};
Error appears like this one below.
oops_case_study.cpp: In constructor ‘Circle<V>::Circle()’:
oops_case_study.cpp:81:12: error: class ‘Circle<V>’ does not have any field named ‘Point’
Circle():Point()
^~~~~
When you call the base class constructor from the derived constructor you also need to specify the template parameter for the bases class, like below.
Circle() : Point<V>()
{
radius=0;
}
note that Point's constructor is called like Point<V>()
Related
class AbstractShape;
class RectangularShape : public AbstractShape
{
void setWidth(double v);
void setLength(double v);
};
class CircleShape : public AbstractShape
{
void setRadius(double v);
};
class PolygonalShape : public AbstractShape
{
void addPoint(Point p);
};
class Element
{
protected:
AbstractShape* _shape; //RectangularShape, PolygonalShape or CircleShape
};
I want to create methods in Element to modify the shape _shape of Element ( ie if the shape is Rectangular I have to be able to change the length and the width, otherwise I have to be able to add a Point to the polygonal shape etc ).
For instance I cannot declare a setLength method because setLength as only a meaning if _shape is a RectangularShape. A solution would be to subclass Element in RectangularElement, PolygonalElement, CircularElement but I would like to avoid this solution.
Do you see another way to do that ?
May be you could do something like following :
class Shape
{
// ....
virtual void setWidth(double v) { /* not implemented, throw error ? */ }
virtual void setLength(double v){ /* not implemented, throw error ? */}
virtual void setRadius(double v){ /* not implemented, throw error ? */}
virtual void addPoint(Point p) { /* not implemented, throw error ? */}
//....
};
class RectangularShape : public Shape
{
void setWidth(double v) override ;
void setLength(double v) override;
};
class CircleShape : public Shape
{
void setRadius(double v) override ;
};
class PolygonalShape : public Shape
{
void addPoint(Point p) override;
};
class Element
{
protected:
Shape* _shape; //Any shape
};
Calling meaningless function on a _shape will print a message or assert .
Other than basic fat interface implementation I mentioned, if you don't want to pollute your abstract base class for whatever reason, one possible solution is to use a fat interface on another class and capability queries
class AbstractShape {};
class RectangularShape : public AbstractShape
{
public:
void setWidth(double v);
void setLength(double v);
};
class CircleShape : public AbstractShape
{
public:
void setRadius(double v);
};
class PolygonalShape : public AbstractShape
{
public:
void addPoint(Point p);
};
class Element {
public:
void setWidth(double);
void setLength(double);
void setRadius(double);
void addPoint(Point);
protected:
std::unique_ptr<AbstractShape> shape;
};
And the implementation of setWidth() for example could look like this
void Element::setWidth(double val) {
if (auto rectangle = dynamic_cast<Rectangle*>(this->shape.get())) {
rectangle->setWidth(val);
} else {
throw std::runtime_error{"This type does not implement setWidth()"};
}
}
Also note that you probably want to use a std::unique_ptr and not a raw pointer.
I am having trouble with my circle constructor which is inherited from the Point2D class.
shape.h:
#pragma once
class Shape {
public:
virtual float area() const = 0;
virtual float circumference() const = 0;
};
Point2D.h:
#pragma once
#include "Shape.h"
template<class T>
class Point2D : public Shape {
protected:
T x, y;
public:
Point2D() : x(0), y(0) { }
Point2D(T x, T y) : x(x), y(y) { }
T getX() const;
T getY() const;
void setX(T x);
void setY(T y);
};
template<class T>
T Point2D<T>::getX() const {
return x;
}
template<class T>
T Point2D<T>::getY() const {
return y;
}
template<class T>
void Point2D<T>::setX(T x) {
Point2D<T>::x = x;
}
template<class T>
void Point2D<T>::setY(T y) {
Point2D<T>::y = y;
}
Circle.h:
#pragma once
#include "Point2D.h"
#include "CustomException.h"
template<class T>
class Circle: public Point2D<T> {
protected:
T x, y, radius;
public:
Circle() : x(0), y(0), radius(0){}
Circle(T x, T y, T radius) : Point2D<T>(x,y), radius(radius) { }
T getRadius() const;
void setRadius(T radius);
virtual float area();
virtual float circumference();
};
template<class T>
T Circle<T>::getRadius() const {
return radius;
}
template<class T>
void Circle<T>::setRadius(T radius) {
Circle<T>::radius = radius;
}
template<class T>
float Circle<T>::area() {
return 3.14*radius*radius;
}
template<class T>
float Circle<T>::circumference() {
return 3.14*2*radius;
}
I get these errors:
error: invalid new-expression of abstract class type ‘Circle<int>’
Circle<int> *circleInt = new Circle<int>(2, 2, 4);
because the following virtual functions are pure within ‘Circle<int>’:
class Circle: public Point2D<T> {
virtual float Shape::area() const
virtual float area() const = 0;
virtual float Shape::circumference() const
virtual float circumference() const = 0;
Why am I getting these errors? How can I fix this?
Just got it! Since I need to override the virtual method area() and circumference() from shape.h, the method of area() and circumference() need to change. And they always need to change to constant method.
virtual float area(); >>>>>> float area() const override;
virtual float circumference; >>>>>> float area() const override;
Someone recommended me to use boost::variant as shape variable to store different types of shapes in it. But, when implemented boost::variant to my code, I got an error while compiling. Error says: 'Shape': base class undefined and more errors.
Here is my code (Object.h):
using Shape = boost::variant<Rectangle, Circle>;
enum Shape_Type
{
RECTANGLE,
CIRCLE
};
struct Position
{
float x, y;
Position(float position_x, float position_y)
{
x = position_x;
y = position_y;
}
};
class Object : private Shape
{
private:
std::string name;
public:
Object() = default;
Object(std::string name, Rectangle rectangle) : name(name), Shape(rectangle)
{
}
Object(std::string name, Circle circle) : name(name), Shape(circle)
{
}
void setPosition(float, float);
void setAngle(float);
Shape* getShape()
{
Shape* shape = this;
return shape;
}
Position getPosition();
const std::string* getName()
{
return &name;
}
};
class Rectangle
{
private:
sf::RectangleShape rectangleshape;
public:
Rectangle() = default;
Rectangle(float width, float height)
: rectangleshape(sf::RectangleShape(sf::Vector2f(width, height)))
{
}
void setPosition(float position_x, float position_y)
{
rectangleshape.setPosition(position_x, position_y);
}
void setAngle(float angle)
{
rectangleshape.setRotation(angle);
}
sf::RectangleShape* getRectangleShape()
{
return &rectangleshape;
}
Position getPosition()
{
return Position(rectangleshape.getPosition().x,
rectangleshape.getPosition().y);
}
};
class Circle
{
private:
sf::CircleShape circleshape;
public:
Circle() = default;
Circle(std::string name, float radius)
: circleshape(sf::CircleShape(radius))
{
}
void setPosition(float position_x, float position_y)
{
circleshape.setPosition(position_x, position_y);
}
void setAngle(float angle)
{
circleshape.setRotation(angle);
}
sf::CircleShape* getCircleShape()
{
return &circleshape;
}
Position getPosition()
{
return Position(circleshape.getPosition().x,
circleshape.getPosition().y);
}
};
And btw is getShape() function good?
Variants are used for static polymorphism, so you don't need the base class at all (that's dynamic - or virtual - polymorphism).
The members in a variant typically do not share a common base class, so you wouldn't have the getShape function, or you'd need to template it:
template <typename T>
T const& getShape() const { return boost::get<T>(_shape); }
I have two classes with same interface methods:
struct ImplGenerated {
int foo(int x, int y);
void bar(double x);
....
};
struct ImplCustom {
int foo(int x, int y);
void bar(double x);
.....
};
And class Wrapper:
struct Wrapper {
Wrapper(ImplGenerated * i): m_generated(i), m_custom(0) {}
Wrapper(ImplCustom * i): m_generated(0), m_custom(i) {}
int foo(int x, int y);
void bar(double x);
....
private:
??? getImpl();
ImplGenerated * m_generated;
ImplCustom * m_custom;
};
int Wrapper::foo(int x, int y) {
return getImpl()->foo(x, y);
}
void Wrapper::bar(double x) {
getImpl()->bar(x);
}
Is it possible to write some C++ construction (class or any other, but not macros) instead getImpl() for resolving current implementation object and call corresponding method?
like this:
???? getImpl() {
return m_custom ? m_custom : m_generated;
}
Note:
Only changes to ImplCustom could be applied (add base class or make template or something else), ImplGenerated is auto-generated by external project therefore couldn't be changed (add base class is impossible).
Wrapper could not be template, because is interface class.
Update:
It is impossible to derive ImplCustom from ImplGenerated.
The solution I see here is to create a wrapper
The goal of this solution is to generate an interface for your two unrelated classes.
Let's start by making a Base classe:
struct ImplInterface {
virtual int foo(int x, int y) = 0;
virtual void bar(double x) = 0;
// ...
};
Now you can create wrapper for each Impl you got:
struct GeneratedWrapper : ImplInterface {
virtual int foo(int x, int y) {
_impl.foo(x, y);
}
virtual void bar(double x) {
_impl.bar(x);
}
private:
ImplGenerated _impl;
};
struct CustomWrapper : ImplInterface {
virtual int foo(int x, int y) {
_impl.foo(x, y);
}
virtual void bar(double x) {
_impl.bar(x);
}
private:
ImplCustom _impl;
};
Now you can use these wrapper like this:
ImplInterface* wrapper = new GeneratedWrapper(implGenerated);
This method could be much shorter using templates, let's make One wrapper for your new interface:
template<typename T>
struct EveryImplWrapper : ImplInterface {
virtual int foo(int x, int y) {
_impl.foo(x, y);
}
virtual void bar(double x) {
_impl.bar(x);
}
private:
T _impl;
};
Now you can use it like this:
ImplInterface* = new EveryImplWrapper<ImplCustom>(implCustom);
If you can't modify the existing classes, you can still add a facade to provide post-hoc polymorphism. That is:
Wrapper could not be template, because is interface class
is only partly true. You can have a non-templated interface (ABC) and a templated concrete subclass.
// publically visible parts
struct ImplInterface {
virtual ~ImplInterface() {}
virtual int foo(int x, int y) = 0;
virtual void bar(double x) = 0;
....
};
struct Wrapper {
// ...
ImplInterface *Wrapper::getImpl();
// ... do you want to keep the same impl selection across calls?
ImplInterface *m_impl;
};
// implementation details can be hidden in a cpp file
template <typename RealImpl>
struct ImplFacade: ImplInterface {
RealImpl pimpl_;
explicit ImplFacade(RealImpl *impl) : pimpl_(impl) {}
int foo(int x, int y) override { return pimpl_->foo(x,y); }
void bar(double x) override { pimpl_->bar(x); }
};
ImplInterface *Wrapper::getImpl() {
if (!m_impl) {
if (m_custom)
m_impl = new ImplFacade<ImplCustom>(m_custom);
else
m_impl = new ImplFacade<ImplGenerated>(m_generated);
}
return m_impl;
}
Ideally you should be using unique_ptr for the new member in real code.
If you can use the c++11 Standard you can use std::function to accomplish this:
struct Wrapper {
Wrapper(ImplGenerated * i):
foo(std::bind(&ImplGenerated::foo, i)),
bar(std::bind(&ImplGenerated::bar, i)) {}
Wrapper(ImplCustom * i):
foo(std::bind(&ImplCustom ::foo, i)),
bar(std::bind(&ImplCustom ::bar, i)) {}
//Now the functions are member variables but it works the same way
std::function<int(int x, int y)> foo;
std::function<void(double x)> bar;
....
//If you don't Need to destruct the impl-objects then you don't even Need to store them
};
I believe what you're wanting is to use inheritance / interface:
struct ImplInterface {
virtual int foo(int x, int y) = 0;
virtual void bar(double x) = 0;
....
};
struct ImplGenerated : public ImplInterface {
virtual int foo(int x, int y);
virtual void bar(double x);
....
};
struct ImplCustom : public ImplInterface {
virtual int foo(int x, int y);
virtual void bar(double x);
.....
};
now your getImpl() will return a ImplInterface*
Or if you can't add a base class, then in your Wrapper class instead of getImpl() do this:
int foo(int x, int y)
{
if (m_generated != nullptr)
{
return m_generated->foo(x,y);
}
else if (m_custom != nullptr)
{
return m_custom->foo(x, y);
}
throw "hey dude!";
}
I know it's a lot of work, but hey you've no base class to work with.
I want to go from this:
To this:
How would I do this? How would the functions of subclasses square and rectangle know to use the variable of the parent class shape?
How would I set length and width from main?
#include <iostream>
#include <cmath>
using namespace std;
class SHAPES
{
public:
class SQUARE
{
int perimeter(int length, int width)
{
return 4*length;
}
int area(int length, int width)
{
return length*length;
}
};
public:
class RECTANGLE
{
int perimeter(int length, int width)
{
return 2*length + 2*width;
}
int area(int length, int width)
{
return length*width;
}
};
};
I recommend other (better?!) format:
class Shape
{
protected:
int length,width;
public:
Shape(int l, int w): length(l), width(w){}
int primeter() const
{
return (length + width) * 2;
}
int area() const
{
return length * width;
}
};
class Rectangle : public Shape
{
public
Rectangle(int l, int w) : Shape(l,w){}
};
class Square : public Shape
{
public:
Square(int l): Shape(l,l){}
};
int main()
{
Rectangle r(5,4);
Square s(6);
r.area();
s.area();
}
Or use interface with virtual function.
Those are not subclasses (i.e. derived classes), but rather nested classes (as the title of your question says).
I don't think I would answer your real question if I were to tell you how to make those variables visible in nested classes. Based on what I can understand from the names of your classes, you should rather use inheritance to model the IS-A relation between them:
class SHAPE
{
public: // <-- To make the class constructor visible
SHAPE(int l, int w) : length(l), width(w) { } // <-- Class constructor
...
protected: // <-- To make sure these variables are visible to subclasses
int length;
int width;
};
class SQUARE : public SHAPE // <-- To declare public inheritance
{
public:
SQUARE(int l) : SHAPE(l, l) { } // <-- Forward arguments to base constructor
int perimeter() const // <-- I would also add the const qualifier
{
return 4 * length;
}
...
};
class RECTANGLE : public SHAPE
{
// Similarly here...
};
int main()
{
SQUARE s(5);
cout << s.perimeter();
}