I want to write an abstract class so whoever inherits it, he will be forced to implement a specific function inside it.
For example I wrote:
class Car {
virtual double getFuelConsumption(int speed) = 0;
};
But If I write the following it compiles with no compilation error (even though it didn't implement getFuelConsumption())
class meme : public Car {};
Update:
Why I'm getting error:
(I know that if it's exactly a car then it doesn't have getFuelConsumption implemented what what if it's a class that inherits class Car, I want this to work)
double getPetrol(std::vector<Road> roads, const Car &car) {
car.getFuelConsumption(1);
}
> 'this' argument to member function 'getFuelConsumption' has type
> 'const Car', but function is not marked const
The code you wrote is OK, as long as nobody instanciates a meme. This is by design.
As far as the compiler is concerned, your plan might very well be:
class meme : public Car
{
};
class ConcreteMeme : public meme
{
virtual double getFuelConsumption(int speed) {return 2.0;}
};
Since you may want intermediate interfaces, there's no issue. The problem shows only when you try to instanciate a class that has a pure virtual method. If the compiler were to prevent you from having meme, you'd end up in a situation where you can't have ConcreteMeme.
The code you have is fine, meme will not be usable at all without the pure virtual method(s) being implemented. The only reason it compiles now is that you haven't actually tried to use it.
Related
Goal:
Sharing a base class with the same functionality except only a few descendants which merely hides methods (getters and setters) as they instantiate and free a protected or private pointer.
Problem:
When re-declaring the setter only I get this error when invoking the getter.
1>c:\projectengine\problem\main.cpp(8): error C2660: 'cDerived::SomeClass'
: function does not take 0 arguments
The getter isn't really needed but why disclose functionality if it's there already.
Conclusion:
cBase::SomeClass() is untouched by cDerived.
When commenting out the next line, no compile error (of course):
virtual void SomeClass( cSomeClass* value ) override {}; // setter, C2660
However that would work, and thus not changing anything, there rises a risk for a memory leak. On the other hand, this accidental derivative should inherited the rest of the functionality of cBase which is a descendant by itself.
Should I rewrite cBase or is it possible to hide only the setter in cDerived?
The code with the error:
main.cpp
class cSomeClass
{
};
class cBase : public cAbsoluteBase
{
public:
cBase() : m_pSomeClass( 0 ){}
virtual cSomeClass* SomeClass(){ return m_pSomeClass; }
virtual void SomeClass( cSomeClass* value ){ m_pSomeClass = value; };
protected:
cSomeClass* m_pSomeClass;
};
class cDerived : public cBase
{
private:
// hide these
//virtual cSomeClass* SomeClass() override { return m_pSomeClass; };
virtual void SomeClass( cSomeClass* value ) override {};
};
cDerived derived;
int main()
{
cSomeClass* someClass = derived.SomeClass(); // C2660
return 0;
}
You need a using declaration. Otherwise, overloads in the derived class hide the functions in the base class. (Because usually this is an error. If you had to specialize one overload, usually you have to specialize all of them.)
I'm not sure I could follow your description accurately, but from the code snippets, it looks like you want to publicly inherit from a class, but remove one of the methods of the base classes interface.
That is possible, it is even possible to do accidentally, but it is a very bad idea™. Public inheritance is an “is-a” relationship. If you have a class B publicly inheriting from class A, then what declaring that relationship means is “objects of type B may be larger than those of type A, but apart from that, you can use a B wherever an A is expected.” Obviously Bs may have additional behavior, but public inheritance promises that they work as fully functional As. (This is known as the “Liskov Substitution Principle,” by the way.)
Note that this is also why one of the early textbook examples for inheritance was utterly broken: Having Square inherit from Rectangle. Yes, a square is a rectangle, but that doesn't mean it is sound OO design to have Square publicly inherit from Rectangle. Because sub-classes having additional restrictions over their parent classes breaks a lot of otherwise perfectly valid and useful code, by not adhering to the established interface contract. (In the case of squares, they break the contract clause that you should be able to change the sides of a rectangle independently from one another. In your case, you seem to be removing parts of the interface altogether.)
After it turned out that what I originally wanted is probably not possible w/o involving C++11 I want to slightly change the requirement and ask you if this can be achieved.
previous question
Basically I want to check in compile time if a class is inheriting from "interface". By interface I mean class with pure virtual methods only.
I would like to do the following code:
template <typename T>
class Impl : public T {
public:
STATIC_ASSERT_INTERFACE(T);
};
The behavior here is if T has only pure virtual methods then it will compile and if one of its methods is not then fail.
Can anyone think of something like that?
This is basically similar to Java interfaces. In C++, there is no existence of interface as such, it's just a terminology used for a class with all pure-virtual methods and only static const data members.
Additionally, pure virtual methods may or may not have a function body. Thus C++ pure virtual methods are not exactly same as Java's abstract methods.
Unfortunately what you are asking is not possible to simulate in C++.
First off, interfaces are not really a native concept to C++. I'm sure most programmers know what they are, but the compiler doesn't, and that's where you're running into problems. C++ can do a lot of things, and I bet you can twist it into looking like a lot of different languages, but if you're going to write C++, it's best to do things the C++ way.
Another thing - there's a lot of grey area here. What if you had an "interface" like you suggested, but somebody did one of these:
// Technically not a member function, but still changes the behavior of that class.
bool operator==(const Interface &left, const Interface &right);
I'm almost 100% sure you can't stop someone from doing that.
You may be able to make sure there are no member variables though, even though I'm not sure I agree with this way of doing things. Make an empty class, and then do a static_assert(sizeof(InterfaceClass) == sizeof(Empty)). I'm not sure if it's safe to assume the size would be 0 - that's a question for someone more familiar with the standards.
What you want can not be done directly, as others have already explained.
However, you can still get the behavior you want with a bit of discipline from the interface developers. If all your interfaces derive from a common base class Interface, you can check that Interface is a base class at compile time using a technique similar to this question.
For example :
class Interface {
public :
virtual ~Interface() { }
};
template <typename T>
struct IsDerivedFromInterface {
static T t();
static char check(const Interface&);
static char (&check(...))[2];
enum { valid = (sizeof(check(t())) == 1) };
};
class MyInterface : public Interface {
public :
virtual void foo() = 0;
};
class MyBase {
public :
virtual void bar() { }
};
class Foo : public MyInterface {
public :
virtual void foo() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Foo>::valid); // just fine
class Bar : public MyBase {
public :
virtual void bar() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Bar>::valid); // oops
Of course, the developer of the base class can cheat and derive from Interface even though the base class is not an interface. Which is why I said it requires some discipline from the developer.
That said though, I can't see how this would be useful. I've never felt I needed this kind of compile time check.
Say I have an abstract class "Base", of which another abstract class "Subclass" extends. Base has a number of abstract member functions, and "Subclass" implements a number of them, but leaves it's own subclasses to provide the implementation of others. Should I include the signature of the member functions which I don't implement in the intermediate class or not?
In other words, assuming I have the following class structure:
Car.hpp:
class Car {
public:
virtual std::string getMake() = 0;
virtual std::string getType() = 0;
virtual ~Car { };
}
SportsCar.hpp:
class SportsCar : public Car {
public:
std::string getType();
// Do I need to specify virtual std::string getMake() = 0; here?
}
SportsCar.cpp:
std::string SportsCar::getType()
{
return "sports";
}
FerrariSportsCar.hpp:
class FerrariSportsCar : public SportsCar {
public:
std::string getMake();
}
FerrariSportsCar.cpp:
std::string FerrariSportsCar::getMake()
{
return "ferrari";
}
Should I still need include virtual std::string getMake() = 0; in SportsCar.hpp?
The code compiles whether I include it or not, and the program seems to execute exactly the same.
You don't need to specify the abstract method again in the intermediate class. It will be inherited by the intermediate class as pure and still require it to be overridden in a further child.
Note that your intermediate class will still be abstract and you couldn't create instances of it.
Since it compiles both ways, this is somewhat a matter of style. I follow a general rule of "do as little work as possible". I think it applies here.
Omitting it will cause a compilation error for those who try to subclass SportsCar without implementing getMake(). Not repeating the definition in the intermediate class makes it easier to change the interface in the future.
There is one case where I would potentially put the intermediate pure virtual for readability purposes, which is when you have something like:
template<typename T>
class Foo : public T {...};
In this case, since it's difficult to find out the type of T, there's some value in putting the extra definition.
Not only you don't need to re-specify pure virtual member function declarations in intermediate classes of your hierarchy, but I would advise against doing so: when programming in C++ one has to get used to look for things in all the places they might legitimately be. By the way this is true also of many other programming languages.
#include <iostream>
using namespace std;
class Duck {
public:
virtual void quack() = 0;
};
class BigDuck : public Duck {
public:
// void quack(); (uncommenting will make it compile)
};
void BigDuck::quack(){ cout << "BigDuckDuck::Quack\n"; }
int main() {
BigDuck b;
Duck *d = &b;
d->quack();
}
The code above doesn't compile. However, when I declare the virtual function
in the subclass, then it compiles fine.
If the compiler already has the signature of the function that the subclass will override, then why is a redeclaration required?
Any insights?
The redeclaration is needed because:
The standard says so.
It makes the compiler's work easier by not climbing up the hierarchy to check if such function exists.
You might want to declare it lower in the hierarchy.
In order to instantiate the class the compiler must know that this object is concrete.
If you change:
virtual void quack() = 0;
to
virtual void quack();
It will compile without implementing quack() in HugeDuck.
the = 0; at the end of the function declaration is essentially saying that all BigDucks will quack, but that it has to be implemented by each derived duck. By removing the = 0; the BigDuck quack will get called unless you implement quack in HugeDuck.
EDIT: To clarify the = 0; is saying that the derived class will have the definition for the function. In your example it is expecting HugeDuck to define quack(), but as you have it commented it out it does not.
As a side note, since all ducks can quack perhaps your original Duck class that we can not see should implement quack() instead?
Because C++ separates 'declaration' from 'polymorphism': any function needs a declaration for the compiler, regardless if it's virtual or not.
Your example doesn't go far enough, it has the 'abstract class' problem: a BigDuck cannot be instantiated because it has no implementation of quack in it's interface.
Generalizing the problem, we can declare the base function not pure virtual:
class Duck { public: virtual void quack(){} };
class BigDuck : public Duck {};
// WRONG: undeclared method definition
void BigDuck::quack(){ cout << "QUACK!"; }
In here, the compiler will complain that it has a symbol BigDuck::quack that wasn't declared. This has nothing to do with abstract classes or anything.
(Note: gcc says:
error: no 'void BigDuck::q()' member function declared in class 'BigDuck'
)
The definition of Quack() in your base class is "abstract" - it has no implementation. This tells the compiler that your derived class must implement it. Failure to do so is a compilation error.
BigDuck could be another abstract class and you might not want to implement quack until you get to the base class ReallyBigDuck.
Until you provide an implementation, all classes that inherit from a class that contains Pure Virtual Function are abstract - they cannot be instantiated. In order to provide such an implementation, you must declare the function in the class.
Declaring the methods in each classes will tell the compiler that class provides the different implementation for the method.
Also,
in case you want to create the objects of BigDuck on stack then how will compiler should know the signature of quack().
BigDuck aDuck;
aDuck.quack();
Is there any issue with partially overriding a set of virtual functions defined by a base class?
My compiler provides the following warning:
overloaded virtual function "MyBaseClass::setValue" is only partially overridden in class "MyDerivedClass".
The classes look like this:
class MyBaseClass
{
public:
virtual void setValue(int);
virtual void setValue(SpecialType*);
}
class MyDerivedClass : public MyBaseClass
{
public:
virtual void setValue(int);
}
The easy way to get rid of this warning is to use different names for the base functions, but I wanted to know if there was any compelling reason to fix this specific warning. I do not believe this violates the C++ standard. My guess is that it's to warn a programmer that they may have forgotten to implement the behavior for all possible input types. In our case, it is intentional to exclude some of the specific types.
Would you discourage suppressing this warning altogether?
The override for setValue(int) hides setValue(SpecialType*) of the base class (see the C++ FAQ Lite), so if you try to call setValue(new SpecialType()) you will get an error.
You can avoid this by adding a using directive to the derived class that "imports" the overloads from the base class:
class MyDerivedClass : public MyBaseClass
{
public:
using MyBaseClass::setValue;
virtual void setValue(int);
};
The warning is correct, it's called "name hiding". A variable of type MyDerivedClass cannot call setValue(SpecialType*).
Now I'm going to blatantly rip off someone else's blog:
Overloading and name hiding in C++
In a phone conversation with Brad last night, he told me about a strange problem he's encountered in his new C++ job. Granted, it's probably no big deal to people with extensive C++ experience, but to those of us who live in managed code worlds, this seemed strange.
In C++, when you have a class with an overloaded method (member function, whatever you want to call it), and you then extend and override that method, you must override all of the overloaded methods.
I understand the case where you have changed a method signature in a child class, thereby invalidating the established interface. In this case, though, it seems counterintuitive, since you're not changing the interface, but selectively overriding. Which is different.
For example:
class FirstClass
{
public:
virtual void MethodA (int);
virtual void MethodA (int, int);
};
void FirstClass::MethodA (int i)
{
std::cout << "ONE!!\n";
}
void FirstClass::MethodA (int i, int j)
{
std::cout << "TWO!!\n";
}
Simple class here with two methods (or one overloaded method). You want to override the two-parameter version, so you continue with the following:
class SecondClass : public FirstClass
{
public:
void MethodA (int);
};
void SecondClass::MethodA (int i)
{
std::cout << "THREE!!\n";
}
Now, when you use an instance of SecondClass, most Java or C# programmers might assume you can call:
int main ()
{
SecondClass a;
a.MethodA (1);
a.MethodA (1, 1);
}
However, the second call won't work, since the two-parameter MethodA is not visible. You can get a pointer and up-cast to FirstClass, but your SecondClass instance doesn't inherit the non-overridden methods directly.
It's clear that the compiler wants to warn you: you created a subclass that behaves differently when giving it an int, but you didn't change it's behavior when giving it a SpecialType*.
Although this might be the intention, it is very very possible that the changed behavior is also needed for the other overloaded virtual functions.
I wish the compiler had warned me harder, the time I ignored it! My overridden method turned out to compile and work well in my scenario, but some other scenario's went really wrong due to the overload not being overridden.
Think twice before you disable that warning!
If you want the original behavior kept, it's easy to just call the parent function:
class MyDerivedClass : public MyBaseClass {
virtual void setValue(int);
// explicit: keep original behavior for SpecialType
virtual void setValue( SpecialType* p ) { MyBaseClass::setValue(p); }
};