I am trying to implement operator overrides (for use in a set). I have a base class and a derived class:
// Base.h
class Base {
public:
virtual bool operator < (const Base&) const = 0;
}
// Derived.h
class Derived : Base {
public:
virtual bool operator < (const Derived&) const;
private:
int num;
}
// Derived.cpp
bool Derived::operator < (const Derived& obj) const {
return num < obj.num;
}
My initial approach threw an error: 'Base': cannot instantiate abstract class when Derived is being used in another file. Is there a way to write a pure virtual function in Base such that all its Derived classes are required to implement it?
This is because there seems to be some redundancy if the same function declaration had to be made in every Derived class (apart from its parameter).
Related
I've been experimenting with CRTP in c++, and I've ran into an issue writing a generic copy constructor for the base class to copy any other derived class. Lets say I have this CRTP base class.
template <class Derived>
class Base {
public:
//Static dispatch function
void print() const {
static_cast<Derived *>(this)->print();
}
protected:
//Protected so it can only be derived
Base(int i) : i(i) { }
//Attempt at a generic copy constructor
template <class Sibling>
Base(const Base<Sibling>& rhs) : i(rhs.i) { }
const int i;
};
Now if I write two derived classes: class Derived1 : public Base<Derived1> and class Derived2 : public Base<Derived2> and I give Derived2 a copy constructor that takes a Derived1 like this:
class Derived2 : public Base<Derived2> {
public:
//Copy constructor
Derived2(const Derived1& rhs) : Base(rhs) { }
...
};
I get a compiler error. error: 'i' is a protected member of 'Base<Derived1>' This is because Derived1, and Derived2 are two unique types that not inside the same class family so they don't have access to non-public members, correct?
In the Base class If I declare template <class Sibling> a class friend of Base it compiles and copies fine, but I only want Base to have access to derived members in the copy constructor. It also works if I change i visibility to public, but this ruins any type of encapsulation.
What would be ideal would be to make the copy constructor a friend function of all derived class.
template <class Derived>
class Base {
...
//Friend Declaration
template <class Sibling>
friend Base::Base(const Base<Sibling>& rhs);
//Generic copy constructor
template <class Sibling>
Base(const Base<Sibling>& rhs) : i(rhs.i) { }
...
};
But this results in the same compiler error. Have I declared the friend function wrong? Or is this just not possible to do? If so is there any other method to convert from one derived class to another?
Assume we have this two classes, with implemented swap-idioms. The copy constructor and assignment operator of the base class are deleted, as it makes no sense. However the swap-method is implemented, as it holds a member.
namespace std
{
template<>
void swap<Base>(Base& a, Base& b)
{
a.swap(b);
}
template<>
void swap<Derived>(Derived& a, Derived& b)
{
a.swap(b);
}
}
class Base
{
public:
Base(int ID) : ID_(ID) {}
virtual std::string getString()=0;
Base(const Base&)=delete;
operator=(const Base&)=delete;
void swap(Base& rhs)
{
std:swap(ID_, rhs.ID_);
}
private:
int ID_;
}
class Derived : public Base
{
public:
Derived(int ID, bool Value) : Base(ID), Value_(Value) {}
virtual ~Derived() {}
Derived(Derived& rhs)
{
std::swap(*this, rhs);
}
virtual std::string getString() {return Value_ ? "True" : "False"}
void swap(Derived& lhs, Derived& rhs)
{
std::swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs);
std::swap(lhs.Value_, rhs.Value_);
}
private:
bool Value_;
}
As seen in many examples, this would be the standard way to do it I suppose.
However, I see a problem with the public Base::swap, as it should not be possible to swap only the abstract base-class!
Wouldn't it be better to remove the template for the Base class and make the Base::swap Method protected:
class Base
{
...
protected:
void swap(Base& rhs, Base &lhs);
}
class Derived : public Base
{
...
public:
void swap(Derived& lhs, Derived& rhs)
{
Base::swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs);
std::swap(lhs.Value_, rhs.Value_);
}
}
Assuming, there is another class derived from base, with the first implementation it would be possible to swap the ID, however the data members of the derived objects would stay the same.
So, am I right thinking that swapping of a abstract class should not be possible from outside?
The copy constructor and assignment operator of the base class are deleted, as it makes no sense.
Actually, this is terrible. Now you made Derived uncopyable! Why? There is no reason to add this restriction. The default copy constructor and assignment operator of Base are perfectly reasonable in the context of copying the most-base class of the hierarchy.
Once you undo that, there's no need to do anything else as std::swap(derived1, derived2) would already do the right thing. The default move construction/operation is correct. It's always good to let the compiler do things for you.
But if you want to override swap anyway, the correct way to do that would be as a non-member friend:
class Base {
...
friend void swap(Base& lhs, Base& rhs) {
using std::swap;
swap(lhs.ID_, rhs.ID_);
}
};
class Derived : public Base {
...
friend void swap(Derived& lhs, Derived& rhs) {
using std::swap;
swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs));
swap(lhs.Value_, rhs.Value_);
}
};
Also, your Derived copy constructor makes no sense. Remove it as per the first paragraph of my answer.
This is a recurrent problem once again. Someone know a easy way to do that? Imagine I have the following:
class Base
{
public:
...
Base property(const std::string& name)=0;
};
class Derived:public Base
{
public:
Derived();
Derived(const Derived&& val);
Base property(const std::string& name)
{
Derived z;
return z;
}
}
There is a way for the Derived::property return being (internally) a Derived copy instead of only Base part copy, and with the Derived move constructor invoked?
May be a stupid question, but really I dont find solution. Why copy constructors on return dont copy the specialized class?
Thanks you!
You can't do this.
Returning by value conceptually (ignoring RVO and move semantics) means making a copy of whatever you return by using the copy constructor of the type which the function is declared to return. If you return a Derived, a copy of type Base will be made and you'll lose the Derived part of the object. This is known as slicing.
If you want to return a Derived object as a Base, you'll need to use pointers.
The only aproximation I can find for who search something similar (related with X3liF, TartanLlama and other responses)
#define overridable(T) ovr<T>
#define return_overload_allowed(TYPE) friend struct ovr<TYPE>; virtual void* clone() const
#define return_overload_basic_allowed(TYPE) friend struct ovr<TYPE>; virtual void* clone() const{return new TYPE(*this);}
template<typename T> struct ovr
{
T* _obj;
ovr(const T& t)
: _obj(reinterpret_cast<T*>(t.clone()))
{;}
ovr(ovr<T>&& v)
: _obj(v._obj)
{
v._obj=nullptr;
}
operator T&()
{
return *_obj;
}
virtual ~ovr()
{
delete _obj;
}
};
class BASE
{
return_overload_basic_allowed(BASE);
public:
virtual overridable(BASE) method1();
virtual ~BASE();
};
class DERIVED: public BASE
{
return_overload_basic_allowed(DERIVED);
public:
virtual overridable(BASE) method1()
{
DERIVED a;
return a;
}
virtual ~DERIVED();
};
DERIVED a;
auto x = a.method1();
BASE& really_derived = x;
This compiles fine. But don't meet practical and smart requiriments... :(
I have searched far and wide for a specific answer to this question, and cannot find it. I am trying to create a base class with a virtual operator> that I can override in the derived class. Currently I'm having problems because declaring the function only requires one input variable (as in "bool operator> (Derived & a)" but attempting to define it in a cpp file tells me that it requires two inputs (as in "bool operator> (Derived & a, Derived & b))
I've tried defining the operator inline, but then I get errors where it thinks the derived class is still abstract because I'm passing in the derived type to the operator as shown above, instead of the base class. But if I pass the base class, then I cannot access the derived member variables I need to make the comparison.
I think I'm missing something simple here but I cannot seem to figure out what it is.
Hopefully you can help.
Thanks
For virtual calls to work from a reference/pointer of the base, you will need to use the base-type in the function, so for example
class Derived : public Base
{
....
bool operator>(Base &a)
{
Derived *pa = dynamic_cast<Derived *>(&a);
return this->something > pa->something; // Or whatever...
}
....
};
If you change the type, it becomes a different function, and when you use the base pointer or reference to refer to operator>, it will use the one in the base-class.
Why don't you leave operator>() non-virtual, und have it call a private virtual function?
Like so:
class Base {
public:
bool operator>(Base &a) {
return implementingFunction(a);
}
private:
virtual bool implementingFunction(Base &a) = 0;
};
#include <iostream>
using namespace std;
class base{
public :
virtual bool operator> (base& obj) { cout<<"b\n";return true;}
virtual ~base(){}
};
class derived: public base{
public:
virtual bool operator> (derived& obj) { cout<<"d\n";return true;}
~derived(){}
};
int main()
{
base *a=new derived(),b;
if(*a>b) { delete a; cout<<"Done!\n"; }
return 0;
}
Old question, but I've hardly seen a useful/correct answer here, so I would add my suggestion:
struct base
{
virtual ~base() = default;
virtual bool operator> (base const& obj) const = 0;
};
struct derived: public base
{
derived(int member) : member(member) {}
int member = 0;
virtual bool operator> (base const& obj) const
{
return member > static_cast<derived const&>(obj).member;
}
};
int main()
{
//in reality one would use a unique_ptr, of course
base* a = new derived(1);
base* b = new derived(0);
if(*a > *b)
{
//do something
}
return 0;
}
Caution: this works safely only if you're sure that the base const& parameter is really a derived const& (as e.g. in CRTP).
If not, you should use a dynamic_cast and add some error handling.
I received homework to make program without casting using constructors so this is my code, I have two classes:
class Base {
protected:
int var;
public:
Base(int var = 0);
Base(const Base&);
Base& operator=(const Base&);
virtual ~Base(){};
virtual void foo();
void foo() const;
operator int();
};
class Derived: public Base {
public:
Derived(int var): Base(var){};
Derived(const Base&);
Derived& Derived::operator=(const Base& base);
~Derived(){};
virtual void foo();
};
here two of my functions of Derived:
Derived::Derived(const Base& base){
if (this != &base){
var=base.var;
}
}
Derived& Derived::operator=(const Base& base){
if (this != &base){
var=base.var;
}
return *this;
}
but I have an error within context when I call these rows
Base base(5);
Base *pderived = new Derived(base); //this row works perfectly
Derived derived = *pderived; // I think the problem is here
thanks for any help
You can only access protected members from another object if that object is of the same type as the object that is trying to access it. In your example the constructor and assignment operator both take in a const Base& so there is no guarantee that the actual object will be of type Derived.
There is an error (VS2010)
error C2248: 'Base::var' : cannot access protected member declared in class 'Base'
at the line
var=base.var;
Derived needs to delegate copying of Base members to Base::operator=, instead of trying to put its grubby little hands on the protected members of another object.