I'm developing a chess game. So, I created an abstract class called Piece and the real pieces implement this class, So I have concrete classes like Pawn, Rook...
The problem is: I need an equal method in the interface to compare two pieces. I'm having problem to it, because I wanted a polimorfic method, that is, a method that could compare a piece to any piece. The problem is I can't declare "Piece o" as an argument to the method cause Piece is an abstract type. How can I do this in C++?
I have the following code:
class Piece
{
public:
virtual ~Piece();
virtual std::string name() = 0;
virtual Color color() const = 0;
virtual Type type() const = 0;
virtual Position position() const = 0;
virtual void moveToPosition(Position p) = 0;
virtual bool isValidMove(Position np, Board &b) = 0;
virtual vector<Movimento>& generateMoves(Board &t) = 0;
virtual bool equal(Piece &o) = 0;
};
maybe do something like
virtual bool operator==(const Piece&) = 0;
no object slicing, u can compare the type and other information..
or you can just implement it in your Piece class, such as
virtual bool operator==(const Piece& rhs) {
if (this.type() == rhs.type()) {
return true;
}
else {
return false;
}
}
actually, you probably don't need operator== overloaded, but instead just a equal method...
I solved my problem changing the defition of Piece to an Abstract class instead of a Interface (in the Java vocabulary). Now my code is less redundant and clearer.
class Piece
{
protected:
std::string m_Name;
Color m_Color;
PieceType m_PieceType;
Position m_Position;
public:
Piece(std::string n, Color c, PieceType t, Position p) :
m_Name(n), m_Color(c), m_PieceType(t), m_Position(p){};
virtual ~Piece();
std::string name() const;
Color color() const;
PieceType pieceType() const;
Position position() const;
bool equal(const Piece&) const;
virtual void moveToPosition(Position p) = 0;
virtual bool isValidMove(Position np, Board &t) = 0;
virtual vector<Move>& generateMoves(Board *b) = 0;
};
Related
I've been looking at this code for few hours and I can't find why I can't instantiate class. So I have interfaces:
class ICloneable {
public:
virtual ICloneable* clone() const = 0;
virtual ~ICloneable() = 0 {}
};
class IPrintable
{
protected:
virtual void print(std::ostream&) const = 0;
public:
virtual ~IPrintable() = 0;
friend std::ostream& operator<<(std::ostream, const IPrintable&);
};
std::ostream& operator<<(std::ostream os, const IPrintable& other) {
other.print(os);
return os;
}
class IComparable {
protected:
virtual bool is_greater(const IComparable& other) const = 0;
virtual bool is_equal(const IComparable& other) const = 0;
public:
virtual ~IComparable() = 0;
virtual bool operator>(const IComparable& other) const {
return is_greater(other);
}
virtual bool operator<(const IComparable& other) const {
return !(is_greater(other) || is_equal(other));
}
virtual bool operator==(const IComparable& other) const {
return is_equal(other);
}
virtual bool operator!=(const IComparable& other) const {
return !(is_equal(other));
}
};
And I have two classes that inherit these interfaces:
class I2DShape : public IComparable, public IPrintable {
public:
virtual void print(std::ostream& os) const override final {
os << "Circumference: " << this->circumference();
}
virtual bool is_greater(const I2DShape& other) const final {
return this->circumference() > other.circumference();
}
virtual bool is_equal(const I2DShape& other) const final {
return this->circumference() == other.circumference();
}
virtual double circumference() const = 0;
virtual ~I2DShape();
};
class IPositionable : public IPrintable, public IComparable {
public:
virtual void print(std::ostream& os) const override final {
}
virtual bool is_greater(const IPositionable& other) const final {
distance_from_origin() > other.distance_from_origin();
}
virtual bool is_equal(const IPositionable& other) const final {
distance_from_origin() == other.distance_from_origin();
}
virtual double distance_from_origin() const {
return sqrt(pow(center().get_x(), 2) + pow(center().get_y(), 2));
}
virtual Point center() const = 0;
virtual ~IPositionable();
};
And in the final these two classes are inherited by one which represents shape:
class Shape2D : public IPositionable, public I2DShape, public ICloneable {
protected:
int num_of_points;
Point* points;
public:
Shape2D() : num_of_points(0), points(nullptr) {}
Shape2D(int num) : num_of_points(num), points(new Point[num]) {}
Shape2D(const Shape2D& other) : num_of_points(other.num_of_points) {
points = new Point[num_of_points];
for (int i = 0; i < num_of_points; i++) {
points[i] = other.points[i];
}
}
Shape2D& operator=(const I2DShape& other) {
}
virtual Shape2D* clone() const override = 0;
virtual ~Shape2D() {
if(points)
delete[] points;
}
};
When I derive Square from Shape2D and make function for cloning, I get error that it's abstract class:
class Square : public Shape2D {
private:
double side;
public:
Square() {}
Square(double s, Point center) : side(s), Shape2D(1) { points[0] = center;}
virtual Point center() const override{
return points[0];
}
virtual double circumference() const override {
return 4 * side;
}
virtual Square* clone() const override final {
return new Square(*this); //error on this line
}
};
Error: object of abstract class type "Square" is not allowed
Since in interfaces you declared destructors with = 0 you are forcing explicit implementation of it in sub-classes which can be instantiated.
There are two ways to fix it.
Make interface classes in standard way with default destructors (no = 0), using {} or = default.
Add explicit destructor for Square
Note that pure virtual destructor with implementation is treated by gcc and clang as an error.
Related SO questions:
Why do we need a pure virtual destructor in C++?
Pure virtual function with implementation
The error was as #HolyBlackCat stated in the comments, with function is_greater and is_equal because they have different parameters when overriden. Simple fix to this was to remove = 0 from those two functions in IComparable so they weren't pure.
Let's say I'm trying to define an abstract base class for "mathematical functions" - i.e. things that look like y=f(x) where both x and y are numeric types, and x is in the "domain" of f. Here's what my abstract base class might look like:
template<typename T>
class AbstractFunction{
public:
virtual bool CheckDomain(T) const = 0;
virtual T operator()(T) const = 0;
};
This says that any concrete class derived from AbstractFunction must implement a CheckDomain method and an "evaluation operator" (). Now what I'd like to do is require that the evaluation operator calls the CheckDomain function before evaluating the function. Is there a neat way to do some sort of "partial implementation" for operator()(T)? Obviously this would mean it's no longer a pure virtual.
I thought I had it figured out with the following construction, but I must be missing something because if I create ConcreteFunction f and try to evaluate f(1.0), it doesn't use the derived class methods (it always returns 0 for CheckDomain(x)).
class AbstractFunction{
public:
virtual bool CheckDomain(double) const = 0;
virtual double EvalFunction(double) const = 0;
virtual double operator()(double);
};
double AbstractFunction::operator()(double x){
bool D = CheckDomain(x);
if(D==1){
return EvalFunction(x);
}
else{
std::runtime_error("Error: Out of Domain");
}
}
class ConcreteFunction : public AbstractFunction{
public:
bool CheckDomain(double x) const {(x>0.0)? 1:0;}
double EvalFunction(double x) const {return x*x;}
// Don't need to define operator(), should inherit from AbstractFunction.
};
I'm sure I'm missing something easy, any thoughts?
Actually, my method works! I just spaced out on my definition of ConcreteFunction::CheckDomain. I did the domain check, but didn't return it! The following code compiles and runs as desired:
#include<stdexcept>
#include<iostream>
class AbstractFunction{
public:
virtual bool CheckDomain(double) const = 0;
virtual double EvalFunction(double) const = 0;
virtual double operator()(double) const;
};
double AbstractFunction::operator()(double x) const{
bool D = CheckDomain(x);
if(D==1){
return EvalFunction(x);
}
else{
throw std::runtime_error("Error: Out of Domain");
}
}
class ConcreteFunction : public AbstractFunction{
public:
bool CheckDomain(double x) const {return (x>0.0)? 1:0;}
double EvalFunction(double x) const {return x*x;}
// Don't need to define operator(), should inherit from AbstractFunction.
};
int main()
{
ConcreteFunction f;
std::cout<<"f(1) = "<<f(2.0)<<std::endl; //OK, returns 4
std::cout<<"f(-1) = "<<f(-1.0)<<std::endl; //Throws runtime error, out of domain.
return 0;
}
Imagine I have abstract base class Shape, with derived classes Circle and Rectangle.
class Shape {};
class Circle : public Shape {};
class Rectangle : public Shape {};
I need to determine if two shapes are equal, assuming I have two Shape* pointers. (This is because I have two instances of vector<Shape*> and I want to see if they have the same shapes.)
The recommended way to do this is double dispatch. What I've come up with is this (greatly simplified here, so that shapes are equal to all other shapes of the same type):
class Shape {
public:
virtual bool equals(Shape* other_shape) = 0;
protected:
virtual bool is_equal(Circle& circle) { return false; };
virtual bool is_equal(Rectangle& rect) { return false; };
friend class Circle; // so Rectangle::equals can access Circle::is_equal
friend class Rectangle; // and vice versa
};
class Circle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
protected:
virtual bool is_equal(Circle& circle) { return true; };
};
class Rectangle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
protected:
virtual bool is_equal(Rectangle& circle) { return true; };
};
This works, but I have to add a separate equals function and friend declaration in Shape for each derived class. Then I have to copy-paste the exact same equals function into each derived class, too. This is an awful lot of boilerplate for say, 10 different shapes!
Is there a simpler way to do it?
dynamic_cast is out of the question; too slow. (Yes, I benchmarked it. Speed matters in my app.)
I tried this but it doesn't work:
class Shape {
public:
virtual bool equals(Shape* other_shape) = 0;
private:
virtual bool is_equal(Shape& circle) { return false; };
};
class Circle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
private:
virtual bool is_equal(Circle& circle) { return true; };
};
class Rectangle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
private:
virtual bool is_equal(Rectangle& circle) { return true; };
};
equals() always returns false, even on identical shapes. It seems dispatch is always choosing the is_equal(Shape&) base function, even when a "more specific" match is available. This probably makes sense but I don't understand C++ dispatch well enough to know why.
When you create methods like this:
virtual bool is_equal(Shape& circle) { return false; };
And in the subclass,
virtual bool is_equal(Circle& circle) { return true; };
These are not the same method. You have two separate virtual methods, neither of which is overridden (they are overloaded not even overloaded, as Ben Voigt pointed out). When you call Shape::is_equal, there is only one version: Shape::is_equal(Shape&)... which is not overridden and always returns false.
You would have to define the separate overloaded methods in the parent class and then override them in the child class. For example,
class Shape {
// Choice between these two methods happens at compile time...
virtual bool is_equal(Circle& circle) { return false; };
virtual bool is_equal(Rectangle& circle) { return false; };
};
class Rectangle : Shape {
// Choice between this and Shape::is_equal(Rectangle&) happens at runtime...
virtual bool is_equal(Rectangle& circle) { return true; };
};
However, using tricks like this, you will probably not approach the performance or simplicity of the way a C programmer would do it:
typedef enum {
SHAPE_CIRCLE,
SHAPE_RECTANGLE
} shape_type_t;
struct shape {
shape_type_t type;
};
struct circle {
shape_type_t type;
...
};
struct rectangle {
shape_type_t type;
...
};
bool shape_equal(struct shape *x, struct shape *y)
{
if (x->type != y->type)
return false;
switch (x->type) {
case SHAPE_CIRCLE:
return circle_equal((struct circle *) x, (struct circle *) y);
case SHAPE_RECTANGLE:
...;
}
}
If overloading and virtual methods are making your code more complicated than the C version, then you may wish to rethink whether you solve this particular problem with overloading and virtual methods.
Double-dispatch has been well studied. The generalization of double-dispatch is called a "multi-method".
Chapter 11 of Modern C++ Design addresses this issue in detail. The approach using dynamic_cast<> that you described is in section 11.3 "Double Switch-on-Type: Brute Force". The author even describes how to automate most of the work and automatically generate the symmetric overloads. Then, the author introduces a logarithmic dispatch based on std::map<> and std::type_info. Finally, the section ends with "Constant-Time Multimethods: Raw Speed" that's (roughly) based on a matrix of callback functions.
The presented solution includes lengthy explanations on handling functors and casts to avoid nasty pitfalls in presence of multiple (and virtual) inheritance.
If you consider implementing multi-methods in C++, I stronly recommend that you read the book and implement the proposed solution.
You could use a type enumeration and static casting if dynamic_cast is too slow...
enum ShapeType
{
SHAPE_TYPE_CIRCLE,
SHAPE_TYPE_RECTANGLE
};
struct Shape
{
virtual ShapeType GetShapeType() const = 0;
virtual bool isEqual(const Shape& other) const = 0;
};
struct Circle : Shape
{
virtual ShapeType GetShapeType() const { return SHAPE_TYPE_CIRCLE; }
virtual bool isEqual(const Shape& other) const
{
if (other.GetShapeType() == SHAPE_TYPE_CIRCLE)
{
const Circle *circle = static_cast<const Circle*>(&other);
// do some circle specific comparison
return true;
}
return false;
}
};
Virtual functions can easily replace dynamic_cast RTTI type-checking, like this: http://ideone.com/l7Jr5
struct Shape
{
struct subtype { enum { Shape, Circle, Rectangle, ColoredCircle }; };
virtual bool is_a( int type ) const { return type == subtype::Shape; }
virtual bool is_equal(const Shape& s) const { return false; }
};
struct Rectangle : Shape
{
virtual bool is_a( int type ) const { return type == subtype::Rectangle || Shape::is_a(type); }
virtual bool is_equal(const Shape& s) const
{
if (!s.is_a(subtype::Rectangle)) return false;
const Rectangle& r = static_cast<const Rectangle&>(s);
return true; // or check width and height
}
};
struct Circle : Shape
{
virtual bool is_a( int type ) const { return type == subtype::Circle || Shape::is_a(type); }
virtual bool is_equal(const Shape& s) const
{
if (!s.is_a(subtype::Circle)) return false;
const Circle& c = static_cast<const Circle&>(s);
return true; // or check radius
}
};
struct ColoredCircle : Circle
{
virtual bool is_a( int type ) const { return type == subtype::ColoredCircle || Circle::is_a(type); }
};
int main(void)
{
Rectangle x;
Shape y;
return x.is_equal(y);
}
--
Why are there 10 copies of the "exact same" function? Shouldn't Rectangle::is_equal(const Rectangle&) const be comparing Rectangle-specific members?
If all rectangles fall into a single equivalence class, as is the case with the code you showed, then you can just have a single virtual function that returns the equivalence class.
In my designs, I move the Shape::operator== method to private and not implement it. The amount of work to correctly resolve this is not worth the effort.
In other words, given a vector of Shape *:
std::vector<Shape *> my_shapes;
I can do the following:
my_shapes.push_back(new Rectangle);
my_shapes.push_back(new Circle);
The problem comes in when comparing objects:
Shape * p_shape_1 = my_shapes[0];
Shape * p_shape_2 = my_shapes[1];
if (*p_shape_1 == *p_shape_2) {...}
The expression is equivalent to:
p_shape_1->operator==(*p_shape_2);
If a virtual or polymorphic operation is in place, this becomes:
Rectangle::operator==((Circle));
In otherwords, there is a great possibility that Rectangle will be comparing itself to a Circle or other Shape; an invalid comparison.
So, in my designs I prohibit equality comparisons based on base class pointers. The only stuff that can be compared using pointers to base classes is the content in the base class.
I usually refer to dynamic_cast and virtual funcntions. If the compiler is not too dumb, dynamic casting one step is not that different than making two jumps in a vtable.
class shape
{
protected:
virtual bool is_equal(const shape* s) const=0;
friend bool oeprator==(const shape& a, cost shape& b)
{ return a.is_equal(&b); }
};
class circle: public shape
{
double radius;
point<duouble> center;
protected:
virtual bool is_equal(const shape* s) const
{
const circle* p = dynamic_cast<const circle*>(s);
return p && p->radius==radius && p->center==center;
}
};
Same for rectangle or whatever other shape.
basically, dual dispatch requires - if N are the classees, N2 functions.
In this way, you just need N functions (one per class).
If you feel dynamic cast to be too slow, you can use an enum, declared in the base class,
and initialized properly by the derived classes.
But this requires you to update the enum values every time a new class will be added.
For example:
class shape
{
protected:
enum shapes_type { no_shape, circle_shape, rectangle_shape };
shapes_type my_type;
virtual bool is_equal(const shape* s) const=0;
friend bool oeprator==(const shape& a, cost shape& b)
{ return a.is_equal(&b); }
shape() :my_type(no_shape)
{}
};
class circle: public shape
{
double radius;
point<duouble> center;
protected:
virtual bool is_equal(const shape* s) const
{
const circle* p = static_cast<const circle*>(s);
return my_type == s->my_type && p->radius==radius && p->center==center;
}
public:
circle() { my_type = circle_shape; }
};
In case relying on a base_defined enum is not acceptable (not known number of possible classes), you can rely on a simple value (e.g.: an integer) that can represent univocally a type with a trick like:
int int_generator()
{ static int x=0; return ++x; }
template<class T>
int id_for_type()
{ static int z = int_generator(); return z; }
class shape
{
...
int my_type;
};
class circle
{
...
circle() { my_type = id_for_type<circle>(); }
};
suppose I have those 2 classes:
class num{
public:
int a;
num(){};
num(int x):a(x){};
num(const num& n):a(n.a){}
virtual bool operator==(const num& n)const = 0;
virtual ~num(){};
};
class tmp: public num{
public:
tmp(){};
tmp(int x):num(x){};
tmp(const num& n): num(n){}
tmp(const tmp& t): num(t.a){}
virtual bool operator==(const num& n)const{
return tmp(n).a == a;
}
virtual ~tmp(){};
};
and something like this in main:
int main() {
num* x = &get(...);
return 0;
}
get return a reference of type tmp (in this case. in general it returns reference to a type that inherits from num)
what I want to do is create another num* y that will point to a copy of *x so that if I change *y I won't change *x. and I can't quite figure out how to do this since num is abstract so I can't create an object of this type to make a copy.
ok and another question.
if I overload << operator:
std::ostream& operator<<(std::ostream& os, const tmp& t){
return os<<t.a<<endl;
}
and then try to do this:
cout<<*x<<endl;
I get an error no match for 'operator<<'
why is that?
You're looking for the prototype pattern, also often called clone pattern.
It's basically a pure virtual method
virtual std::unique_ptr<num> clone() const = 0;
... that you declare in num, to be overriden by each derived class. You then just call x->clone(); to get a brand new object of the correct type.
You'll need a virtual function to clone an object based on its dynamic type. It will have to return a (preferably smart) pointer to a newly allocated object of the correct type. For example:
class num {
public:
virtual std::unique_ptr<num> clone() const = 0;
// other members...
};
class my_num : public num {
public:
virtual std::unique_ptr<num> clone() const {
return std::make_unique<my_num>(*this);
}
// other members...
};
int main() {
num* x = &get(...);
auto y = x->clone();
}
Given the following excerpts:
class Interface {
public:
virtual bool operator==(const Interface &other) const = 0;
virtual void print(ostream& sout) const = 0;
};
class A : virtual public Interface {
public:
virtual bool operator==(const Interface &other)const;
virtual void print(ostream& sout)const;
protected:
short m_foo;
};
class B : virtual public Interface {
public:
virtual bool operator==(const Interface &other)const;
virtual void print(ostream& sout) const;
protected:
short m_bar;
};
class C: public A, public B {
public:
virtual bool operator==(const Interface &other) const;
virtual void print(ostream& sout) const;
};
In C.cpp I'm trying to implement operator==:
bool C::operator==(const Interface &other) const {
try {
// This works, but it's duplicating code from A.cpp and B.cpp
const C& otherC = dynamic_cast<const C&>(other);
return (m_foo == otherC.m_foo && m_bar == otherC.m_bar);
// This doesn't work -- it calls C::operator== instead of
// A::operator== and B::operator== (infinite recursion).
/*
return (dynamic_cast<const A&>(*this) ==
dynamic_cast<const A&>(other) &&
dynamic_cast<const B&>(*this) ==
dynamic_cast<const B&>(other));
*/
} catch (bad_cast e) {
return false;
}
}
I can get it to work for the output method, but I don't know how to do
something equivalent when overriding operators:
void C::print(ostream& sout) const {
A::print(sout);
sout << " ";
B::print(sout);
}
Is there a way to call the base classes' virtual operators instead of doing
something like adding a virtual equals() method and just having operator== call
that?
(Note: this code is based off of a small part of a homework assignment in case
that's relevant.)
You need to explicitly name the operator you want to use.
Replace:
return (dynamic_cast<const A&>(*this) ==
dynamic_cast<const A&>(other) &&
dynamic_cast<const B&>(*this) ==
dynamic_cast<const B&>(other));
With Edit: corrected
return (A::operator==( other ) &&
B::operator==( other ));
return A::operator==(other) && B::operator==(other);
The two base classes should handle any type error in other, so you don't need to do anything about that here.
EDIT: rewrote code to use explicit call.