Just a small annoyance really as I can work around the problem by wrapping the derived function instead of using the 'using' keyword but why doesn't the following work (the compiler tells me that 'get_elem' is still pure virtual in 'Bar' class).
class Elem {};
class DerivedElem : public Elem {};
class Foo {
public:
virtual Elem& get_elem() = 0;
};
class Goo {
protected:
DerivedElem elem;
public:
DerivedElem& get_elem() { return elem; }
};
class Bar : public Foo, public Goo {
public:
using Goo::get_elem;
};
int main(void) {
Bar bar;
}
Cheers,
Tom
If Goo is a "mixin" designed to implement the interface Foo in a particular way (there could be other mixins with other implementations), then Goo can derive from Foo (instead of Bar doing so).
If Goo isn't designed to implement the interface Foo, then it would be a terrible mistake to treat Bar as though it had implemented that pure virtual function, when it fact it just happens to have a function of the same signature. If you want implicit interfaces and "duck" typing in C++ you can do it, but you have to do it with templates. Rightly or wrongly, pure virtual functions are for explicitly declared interfaces, and Goo's get_elem function is not explicitly declared to implement Foo::get_elem. So it doesn't.
I guess that doesn't explain why in principle the language couldn't define using Goo::get_elem for Foo;, or some such declaration in Bar, to avoid the need for Bar to contain a lot of boilerplate wrapping the call.
You can maybe do something with templates to allow Goo to support this to some extent, without really knowing about Foo:
template <typename T>
class Goo : public T {
protected:
DerivedElem elem;
public:
DerivedElem& get_elem() { return elem; }
};
class Bar : public Goo<Foo> {};
class Baz : public Goo<Fuu> {};
Where Fuu is some other interface that has a get_elem function. Obviously it's then the responsibility of the author of Bar to ensure that Goo really does implement the contract of Foo, and the same for Baz checking the contract of Fuu.
By the way, this form of covariance is a bit dodgy. Looking at Foo, someone might expect the expression bar.get_elem() = Elem() to be valid, and it isn't, so LSP is violated. References are funny like that. ((Foo &)bar).get_elem() = Elem() is valid but in general doesn't work! It only assigns to the Elem sub-object, and for that matter so does ((Foo &)bar).get_elem() = DerivedElem(). Polymorphic assignment is basically a nuisance.
In your example, the Foo and Goo are separate classes. In Bar, the method get_elem from Goo is not at all the same with the one in Foo, even if their signature match.
By having using Goo::get_elem, you simply tell the compiler to resolve unqualified call to get_elem() to the one in Goo.
You've encountered one of the many odd corners of C++. In this case C++ does not consider two virtual functions inherited from different classes to be the same function even though they have the same name and type signature.
There are some good reasons for C++ to act this way. For example, it's frequently the case that those two functions really aren't the same, despite the fact they have the same name and type signature. The semantic meaning of the two functions are different.
Here is an example:
namespace vendor1 {
class Circle {
public:
virtual ::std::size_t size() const { return sizeof(*this); }
};
} // namespace vendor1
namespace vendor2 {
class Shape {
public:
virtual double size() const = 0;
};
class Circle : public Shape {
public:
virtual double size() const { return radius_ * radius_ * M_PI; }
};
} // namespace vendor2
And then you try this:
namespace my_namespace {
class Circle : public ::vendor1::Circle, public ::vendor2::Circle {
// Oops, there is no good definition for size
};
So you have to resort to this:
namespace my_namespace {
class Vendor1Circle : public ::vendor1::Circle {
public:
virtual ::std::size_t data_structure_size() const { return size(); }
};
class Vendor2Circle : public ::vendor2::Circle {
public:
virtual double area() const { return size(); }
};
class Circle : public Vendor1Circle, public Vendor2Circle {
// Now size is still ambiguous and should stay that way
// And in my opinion the compiler should issue a warning if you try
// to redefine it
};
So, C++ has good reason to treat virtual functions with the same type signature (the return type is not part of the type signature) and name from two different bases as different functions.
As far as using goes... All a using directive says is "Add the names from this other namespace to this namespace as if there were declared here.". This is a null concept as far as virtual functions are concerned. It merely suggests that any ambiguity when using a name should be resolved a different way. It only declares a name, it doesn't define the name. In order for a virtual function to be overridden a new definition is required.
OTOH, if you put in a simple thunk redefinition inline like this:
class Bar : public Foo, public Goo {
public:
virtual DerivedElem& get_elem() { return Goo::get_elem(); }
};
a good compiler should see that and know to not even bother to create the function, and instead just fiddle the virtual table entries to do the right thing. It may need to actually emit code for it and have the symbol available in case its address is taken, but it should still be able to simply fiddle the virtual table into having the function completely disappear when called through a Foo *.
Related
I have a class A and class B which both have the same methods and variables, but B has one additional variable (which is completely independent from other class members).
So it would be something like:
class A
{
void Foo();
bool m_var;
}
template< class T >
class B< T >
{
// Same stuff
void Foo();
bool m_var;
// Unique stuff
T m_data;
}
Normally, I would use inheritance B : public A, but I want to keep these classes super tight and I don't want to have vtable ptr inside them (as I'm not gonna use polymorphy anyway). What's the best approach to achieve that? I was thinking about templates and their specialization - having class A<T> and A<void>, but I need to remove something, not add. Is there any smart template trick which I could use?
I was also thinking about creating base class (without virtual dtor) with all common functionalities as a private nested class and inherited classes A< T > : public Base and empty B : public Base as public nested classes. It wouldn't allow anyone from outside to use base class ptr, but it doesn't sound like the purest solution... Is there any "valid" solution for my problem?
As long as you don't use the word virtual, you won't get a vtable. But you're right to think that inheritance is an awkward solution to this problem. Languages like Rust, Scala, and Haskell have a unit type () for data we don't care about. C++ approximates this (albeit poorly) with void, but it really only works as a function return type. My recommendation is to create your own well-behaved unit type.
struct Unit {};
Nice, empty type. There's only one meaningfully distinct instance of Unit, namely Unit(). Then A is just B<Unit>. The Unit m_data in B<Unit> contains no actual information and will likely be optimized out by the compiler.
As already answered, vtable pointers are only added to a class when they are needed. As long as there is nothing marked as virtual anywhere in either your base or derived class, the compiler will not generate a vtable for your type.
If you want to reuse A when writing B, why can't you just use plain old composition?
class A {
bool _var;
public:
explicit A(bool v);
void foo();
// accessors, which could be constexpr
bool var() const; // get
void var(bool n_v); // set
};
template<class T>
class B {
T _data;
A _a;
public:
B( /* params */);
void foo() { this->_a.foo(); }
// forward to A
bool var() const { return this->_a.var(); } // get
void var(const bool n_v) { this->_a.var(n_v); } // set
// add more stuff here
};
If you really are into nasty shenanigans, you might consider taking the private inheritance route, which is functionally the same thing (but less clean, IMHO):
template<class T>
class B : private A {
T _data;
public:
B( /* params */);
using A::foo; // reexports A::foo() as B::foo()
// generates
// - bool B::var()
// - void B::var(bool)
using A::var;
// add more stuff here
};
Let's say I have a nice looking base class called base:
class base
{
public:
virtual void foo() const = 0;
};
Now, I have a class named foo that I would like to inherit from base and override base::foo:
class foo : public base
{
public:
virtual void foo() const override;
};
This is illegal in C++, as you are not allowed to name a method the same thing as the class (C++ greedily believes methods with the same name as the class are constructors, which are not allowed to have return types). Is there any way around this that doesn't involve changing the name of the class or method? I want external users to be able to create foo classes without the knowledge that there is a method base::foo called by someone else (imagine foo can be both a noun and a verb).
Is there any way around this that doesn't involve changing the name of the class or method?
No, there isn't.
All methods named foo are special in class foo -- they are constructors. Hence, they cannot be overridden virtual member functions.
I'll take a wild guess and just say NO.
You can have a lot of ambiguities in C++ (that sometimes have to be explicitly disambiguated), but I don't even see a way how a compiler or programmer could disambiguate this situation. Well, A programmer can (a function with a return type is obviously not a constructor), but C++ can't.
In C++, the only method that can have the class' name is its constructor.
So, no. You can't.
Okay, here's my (slightly evil) solution...
// Create an intermediate class which actually implements the foo method:
class foo_intermediate : public base
{
public:
virtual void foo() const override;
};
// Derive from that class and forward the constructor along
class foo : public foo_intermediate
{
public:
using foo_intermediate::foo_intermediate;
private:
friend class foo_intermediate;
// Actual implementation for the foo function goes here
void foo_impl() const;
};
// In some CPP file:
void foo_intermediate::foo() const
{
// Need to access the typename foo via namespace (global here)
static_cast<const ::foo*>(this)->foo_impl();
}
Actually calling foo is a bit funny, since this can't work:
void bar()
{
foo x;
x.foo(); // <- illegal attempt to access to the foo constructor
}
You must access through an alias:
void baz()
{
foo x;
base& rx = x;
rx.foo(); // legal
}
As an alternative, you can use a typedef:
class foo_impl : public base
{
public:
virtual void foo() const override;
};
using foo = foo_impl;
This gets around the issue of calling x.foo(), since it no longer appears as a constructor access.
I made a Gist so others could play with the two solutions if they are so inclined.
I have several classes D with public sections of the form:
class D
{
public:
D& foo();
void bar(D&);
}
I'd like to create a single abstract class from which they all derive.
My (naive) attempt was:
// in .h file
class B
{
public:
virtual B& foo() = 0;
virtual void bar(B&) = 0;
}
class D : public B
{
public:
D& foo() override;
void bar(D&) override;
}
// in .cpp file
D& D::bar() {return *(new D());}
void D::foo(D& d) {}
This failed to compile for (what I eventually realized was) a fairly sensible reason: Any function overriding the function
void bar(B&)=0;
must be defined for any parameter which is a reference to type B. The supplied candidate
virtual void bar(D&) override;
is only defined for (the smaller collection) of parameters which are references to type D.
Note that this is not a problem with the function foo. Indeed, if you comment out the three lines with bar, everything compiles fine.
I think that the technical explanation for this phenomenon is that C++ does not support covariance in parameters (but it does support contravariance in parameters).
The answer to the post C++ covariance in parameters suggests that I can't define an interface (i.e. an abstract class) for my classes D.
Is there some simple or conventional way to create a single "interface" for all my classes D? Alternatively, perhaps there is a different design pattern for hiding the different implementations of these classes.
Thanks in advance for your comments and suggestions.
dan
You can't, and for good reason. A derived class can't add preconditions that are more restrictive than the interface it derives from without breaking every principle of OOP that exists. By requiring the parameter to be more specific in your implementation of the interface this is exactly what you are doing.
An argument could be made that something like this could be useful:
struct IfaceA {};
struct IfaceB : IfaceA {};
struct Base { void f(IfaceB &); };
struct Derived : Base { void f(IfaceA &); };
This lessens preconditions rather than increase them, so it's OK. It's simply not done in C++, or any other language I'm aware of for that matter, so you just can't do it.
In both cases you can make an overload with the alternative parameter type and call the overridden version.
It's the opposite case with return types. Return values are post-conditions. You can make post conditions more specific, but can't make them more broad. So you can return your derived type but can't broaden it by returning a more abstract type. C++ implements covariant returns though at least one, very commonly used compiler does it very badly so that there are numerous bugs.
Based on the code that you have provided you have tried to override two diferent function signatures.
The best option you have is use the same signature, and then cast the result.
A simple example,
// in .h file
class B
{
public:
virtual B* foo() = 0;
virtual void bar(B*) = 0;
};
class D : public B
{
public:
B* foo() override;
void bar(B*) override;
};
// in .cpp file
B* D::foo()
{
D* p=new D();
return p;
}
void D::bar(B* d)
{
D* casted=dynamic_cast<D*>(d);
}
int main(void)
{
D son;
B* father=dynamic_cast<B*>(son.foo());
}
I hope that this can solve your problem, or at least give you a clue.
Could you use a templated base class?
template <typename Deriving>
struct Base {
virtual Deriving& foo() = 0;
virtual void bar(Deriving&) = 0;
};
struct Deriving : public Base<Deriving> {
...
};
You don't have a single interface class, but there is a single interface template, which is sometimes versatile enough.
This code
struct Foo{
void f(){
f(0);
}
private:
void f(int){}
};
struct Bar : private Foo{
using Foo::f;
};
int main() {
Bar b;
b.f();
}
fails to compile because Foo::f(int) is private. I am not interested in Foo::f(int), I just want Foo::f() which is public, so I feel there should be a way to do it.
There are some workarounds I can think of:
rename Foo::f(int) to Foo::p_f(int), but that is redundant and disallows overload resolution for f
implementing Bar::foo(){Foo::f();} becomes a lot of copy/paste for multiple public fs
inheriting publicly from Foo which invites UB since ~Foo() is not virtual (and is not supposed to be)
making all fs public makes it too easy to accidentally break Foo and Bar
Is there a way to say using public Foo::f;? Or use one of the workarounds without the associated downsides?
If your f(int) is supposed to be private, and will never ever be part of a public API, then you should not care about renaming it to fimpl:
struct Foo{
void f(){
fimpl(0);
}
private:
void fimpl(int){}
};
If, on the other hand, f(int) is the general version of a public API, and you also want a single convenience wrapper with a particular value, you can use provide a default argument and make f(int) a public member.
struct Foo{
void f(int = 0){}
};
Finally, if you want several named functions that provide certain integer values, then I'd suggest renaming those wrappers
struct Foo{
void f(int) {} // general interface
void sensible_name1() { f(0); }
void sensible_name2() { f(1); } // etc.
}
Your code currently derives Bar from Foo as private. Due to that, Foo::f() is a private method in Bar. You can change that by changing your class declaration to struct Bar: public Foo.
For some background, see the Section on "Private Inheritance" under Derived Classes. Specifically, the section explains that:
[w]hen a class uses private member access specifier to derive from a base, all public and protected members of the base class are accessible as private members of the derived class (private members of the base are never accessible unless friended).
Let's suppose we have a base class which has a virtual method:
class BaseClass
{
virtual void MethodToOverride() const
{
DoSomething();
}
};
And a derived class which overrides the method (depending on the situation we can make it again virtual or not):
class DerivedClass : public BaseClass
{
void MethodToOverride() const
{
DoSomethingElse();
}
}
If we make a mistake, for example defining the MethodToOverride non const or with a wrong character, we simply define a new method, for example:
void MethodToOverride() {} // I forgot the const
void MthodToOverride() const {} // I made a typo
So this compiles fine, but causes unwanted behavior at runtime.
Is there any way to define a function as an explicit override of an existing one, so the compiler warns me if I define it wrongly? Something like (I know it does not exist):
void MethodToOverride() const overrides BaseClass::MethodToOverride() const {}
The best way is to declare the method to be pure virtual in BaseClass.
class BaseClass
{
virtual void MethodToOverride() const = 0;
};
If implementing classes are inherited again (which I would put in question as a semi good practice), there is no way to control the correct implementation.
[[override]] attribute. However it is a part of C++0x.
If you are using gcc consider the -Woverloaded-virtual command-line option.
C++0x offers an attribute for this (see vitaut's answer), and e.g. Visual C++ offers a language extension.
But in portable C++98 the best you can do is a sanity check, that the base class offers an accessible member function that accepts the same arguments, like ...
// The following macro is mainly comment-like, but performs such checking as it can.
#define IS_OVERRIDE_OF( memberSpec, args ) \
suppressUnusedWarning( sizeof( (memberSpec args, 0) ) )
where
template< typename T >
inline void suppressUnusedWarning( T const& ) {}
You call the macro in your override implementation, with the function's actual arguments.
EDIT Added call example (disclaimer: untouched by compiler's hands):
class BaseClass
{
protected:
virtual void MethodToOverride() const
{
DoSomething();
}
};
class DerivedClass : public BaseClass
{
protected:
void MethodToOverride() const
{
IS_OVERRIDE_OF( BaseClass::MethodToOverride, () );
DoSomethingElse();
}
};
Using such a sanity check can improve the clarity of the code in certain cases, and can save your ass in certain cases. It has three costs. (1) Someone Else might mistake it for a guarantee, rather than just an informative comment and partial check. (2) the member function can't be private in the base class, as it is in your example (although that's perhaps positive). (3) Some people react instinctively negatively to any use of macros (they've just memorized a rule about badness without understanding it).
Cheers & hth.,
If your base class may be an abstract one, then the solution is to make the methods you want to be overriden pure virtual. In this case the compiler will yell if you try to instantiate the derived class. Note that pure virtual functions can also have definitions.
E.g.
class BaseClass
{
virtual void MethodToOverride() const = 0;
//let's not forget the destructor should be virtual as well!
};
inline void BaseClass::MethodToVerride const()
{
DoSomething();
}
//note that according to the current standard, for some inexplicable reasons the definition
//of a pure virtual function cannot appear 'inline' in the class, only outside
If you cannot afford your base class to be abstract, then C++03 gives little to do and #vitaut's answer gives what you need for C++0x.
There was a sentence in your question which alarmed me. You say you can choose to make the method further virtual or not. Well, you can't, in C++03. If the method has been declared virtual it will be virtual throughout the hierarchy, whether you explicitly specify it or not. E.G.
class A
{
virtual void f(){}
} ;
class B: public A
{
void f(); //same as virtual void f();
};
You can try this: :)
#include <iostream>
using namespace std;
class Base
{
public:
virtual void YourMethod(int) const = 0;
};
class Intermediate : private Base
{
public:
virtual void YourMethod(int i) const
{
cout << "Calling from Intermediate : " << i << "\n";
}
};
class Derived : public Intermediate, private Base
{
public:
void YourMethod(int i) const
{
//Default implementation
Intermediate::YourMethod(i);
cout << "Calling from Derived : " << i << "\n";
}
};
int main()
{
Intermediate* pInterface = new Derived;
pInterface->YourMethod(10);
}
I think the code speaks for itself. Base makes sure you implement the function with the correct signature (As a side effect makes you always implement it, even though you can use default behavior) while Intermediate which is the interface makes sure that there is a default implementation. However, you are left with a warning :).