I have this code:
#include <iostream>
using namespace std;
class FooA {
public:
virtual void meth () {cout << "hiA\n";}
};
class FooB : public FooA{
public:
void meth () {cout << "hiB\n";}
};
class FooC : public FooB {
public:
void meth () {cout << "hiC\n";}
};
int main() {
FooA a;
a.meth();
FooB b;
b.meth();
FooC c;
c.meth();
FooA* ptr = &a;
ptr->meth();
ptr = &b;
ptr->meth();
ptr = &c;
ptr->meth();
FooB* ptrB = &b;
ptrB->meth();
ptrB = &c;
ptrB->meth();
}
The output is this:
hiA
hiB
hiC
hiA
hiB
hiC
hiB
hiC
The code is basic and self-explanatory. I tried different combinations of making meth() in each class virtual or not. This will change how the output, obviously, especially if FooA::meth() is not declared as virtual. I have come to the conclusion that it is probably best and most clear to just make every instance of that method virtual. Is there any reason not to?
Edit:
I have another question. When you declare a class, and then define it outside of the class declaration, using ::
Like this
class Foo{
public:
virtual void bar();
};
void Foo::bar {
cout << "Hello";
}
Why can't I do something like
virtual void Foo::bar {
cout << "Hello";
}
Is there any reason not to?
It's superfluous.
If you have a method in a base class declared as virtual, this virtuality will be "inherited" by the overriding method.
Other than that, maybe for documentation purposes it might be acceptable. However, remember that the best virtuals are private, employ the non-virtual interface idiom.
With that done, the "for documentation" reason falls to the ground, since private methods need no public documentation.
Yes, when you don't want a derived class to override the implementation of meth() for some reason.
If you think a derived class might need to change the implementation of meth(), make the method virtual.
Related
I am learning and playing around with inheritance and abstract classes. I've run into a predicament that I would appreciate some clarifications on.
I am trying to override a non-virtual function from an abstract grandparent class. I am getting an error saying that 'member function declared with 'override' does not override a base class member.
I can call the original non-virtual function from child class instances in main(), but not override them in child classes?
Here's the code.
UPDATE:
Error went away when I marked the function as virtual, I would still appreciate an explanation as to why that virtual is necessary?
#include <iostream>
using namespace std;
class A
{
public:
virtual string GetClassName() = 0;
void foo(); // <--- this is the problem function
{
cout << "foo" << endl;
}
};
class B : public A
{
public:
string GetClassName() override
{
return "B";
}
};
class C1 : public B
{
public:
string GetClassName() override
{
return "C";
}
};
class C2 : public B
{
public:
void foo() override // ERROR:member function declared with override does not override a base class member.
{
cout << "foo c1" << endl;
}
};
// testing interface
void printName(A* ptr)
{
cout << ptr->GetClassName() << endl;
}
int main()
{
B* b = new B();
C1* c1 = new C1();
C2* c2 = new C2();
printName(b); // prints B
printName(c1); // prints C
printName(c2); // prints B
b->foo(); // prints foo, inherited directly from abstract class
c1->foo(); // prints foo, inherited directly from abstract class
c2->foo(); // ??
}
You cannot override a non-virtual function. It is as simple as that.
Methods in child classes can hide methods of parent classes when they have the same name, for example:
struct A {
void foo(){}
};
struct B : A {
void foo() {}
};
But thats not overriding. To override the method must be virtual. Thats one of the conditions that the override specifier helps to check:
struct A {
virtual void foo(){}
};
struct B : A {
void foo() override {} // <- error if A::foo is not virtual
};
PS: I have seen poor tutorials, that use the first example and call that overriding. Thats just wrong.
In this example
class A
{
public:
A();
~A();
virtual void func1();
virtual void func2();
protected:
virtual void func3();
private:
// How do I mock this
NetworkClass b;
}
How do I mock NetworkClass b object?
I don't think it's possible to do this solely using google-mock macros.
You'd have to redefine the identifier NetworkClass to actually mean NetworkClassMock and then (for purpose of the test) rename the original NetworkClass to something else like NetworkClass_Orig.
But that still doesn't help you access the private member NetworkClass b for the purpose of the test.
You cannot mock b as it is. You will need to use Dependency Injection.
First you will need to specify a Base Class (or interface) and derive your NetworkClass and NetworkClassMock from INetworkClass. Then you can pass aa raw pointer (better a smart pointer like std::unique_ptr) or a reference to class A. This input can be either your real implementation NetworkClass or your mock NetworkClassMock.
See this example:
#include <iostream>
class INetworkClass
{
public:
virtual void doSomething() = 0;
};
class NetworkClass : public INetworkClass
{
public:
void doSomething() override {std::cout << "Real class" << std::endl;} ;
};
class NetworkClassMock : public INetworkClass
{
public:
void doSomething() override {std::cout << "Mock class" << std::endl;};
};
class A
{
public:
A(INetworkClass& b) : b(b) {};
~A() {};
void func1() {b.doSomething();};
private:
// How do I mock this
INetworkClass& b;
};
int main(){
NetworkClass real_class;
NetworkClassMock mock_class;
A a1(real_class);
A a2(mock_class);
a1.func1();
a2.func1();
return 0;
}
If you just want to access your private member, e.g. to read it's value after doing some tests you should redesign your code. Accessing private members from outside your class is not a good design. If you still want to do this you could check this answer (written for C# instead of C++ but still usable).
P.S. To use the override keyword you will need to compile with C++11 support.
Can I have a virtual function in the base class and some of my derived classes do have that function and some don't have.
class A{
virtual void Dosomething();
};
class B : public A{
void Dosomething();
};
class C : public A{
//Does not have Dosomething() function.
};
From one of my c++ textbook:
Once a function is declared virtual, it remains virtual all the way down the inheritance, even if the function is not explicitly declared virtual when the derived class overrides it.
When the derived class chooses not to override it, it simply inherits its base class's virtual function.
Therefore to your question the answer is No. Class c will use Class A's virtual function.
Derived classes do not have to implement all the virtual functions, unless it is a pure virtual function. Even in this case, it will cause an error only when you try to instantiate the derived class( without implementing the pure virtual function ).
#include <iostream>
class A{
public :
virtual void foo() = 0;
};
class B: public A{
public :
void foo(){ std::cout << "foo" << std::endl;}
};
class C: public A{
void bar();
};
int main() {
//C temp; The compiler will complain only if this is initialized without
// implementing foo in the derived class C
return 0;
}
I think the closest you might get, is to change the access modifier in the derived class, as depicted below.
But, I would consider it bad practice, as it violates Liskov's substitution principle.
If you have a situation like this, you might need to reconsider your class design.
#include <iostream>
class A {
public:
virtual void doSomething() { std::cout << "A" << std::endl; }
};
class B : public A {
public:
void doSomething() override { std::cout << "B" << std::endl; };
};
class C : public A {
private:
void doSomething() override { std::cout << "C" << std::endl; };
};
int main(int argc, char **args) {
A a;
a.doSomething();
B b;
b.doSomething();
C c;
//c.doSomething(); // Not part of the public interface. Violates Liskov's substitution principle.
A* c2 = &c;
c2->doSomething(); // Still possible, even though it is private! But, C::doSomething() is called!
return 0;
}
Sample code
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Func()
{
cout << "\nIn base func";
}
};
class Derived : public Base
{
public:
void Func()
{
cout << "\nIn derived";
}
};
class Derived2 : public Derived
{
public:
void Func()
{
cout << "\nIn derived2";
}
};
int main()
{
Base* lnewbase = new Derived2();
lnewbase->Func();
return 0;
}
As an example, in the above code, I do not want Func() of Derived to be inherited (seal in C#) which is why there is no virtual keyword although I am aware that it does not change anything in this case. Is there any way to disallow that function to be inherited while making sure it remains a public method?
No; C++ has no equivalent to C#'s sealed modifier.
There is nothing you can do.
Once you make a function in a base class virtual, there's nothing that can be done to get rid of that aspect of it. I can only think of a few things to almost get around it:
Don't make it virtual;
Make a new, public, non-virtual function in Derived that does what you need.
However, in either case, Derived2 will still be able to make its own version of Func(), which will give you the same problem.
i have a problem in properly handling method overriding where an abstract class is present
inside my classes hierarchy.
I'll try to explain:
class AbstractClass{
public:
virtual void anyMethod() = 0;
};
class A : public AbstractClass {
void anyMethod() {
// A implementation of anyMethod
cout << "A";
}
};
class B : public AbstractClass {
void anyMethod() {
// B implementation of anyMethod
cout << "B";
}
};
AbstractClass *ptrA, *ptrB;
ptrA = new A();
ptrB = new B();
ptrA->anyMethod(); //prints A
ptrB->anyMethod(); //prints B
Ok..previous example work fine .. the concrete implementation of the AbstractClass
method anyMethod will be called at run time.
But AbstractClass is derived from another base class which has a method not virtual
called anyMethod:
class OtherClass {
public:
void anyMethod() {
cout << "OtherClass";
}
};
class AbstractClass : public OtherClass {
public:
virtual void anyMethod() = 0;
};
//A and B declared the same way as described before.
Now , if i try something like that:
ptrA = new A();
ptrB = new B();
ptrA->anyMethod(); //prints OtherClass
ptrB->anyMethod(); //prints OtherClass
What am I misunderstanding?
Is there any solution for making ptrA and ptrB printing A and B without using cast, typeid, etc?
Why don't you do:
class OtherClass
{
public:
virtual void anyMethod()
{
cout << "OtherClass";
};
}
That should solve your problems
If anyMethod was declared virtual in the base class to which you have a pointer or reference, it should be looked up virtually and print A and B correctly. If it wasn't, then there is nothing you can do (beyond changing it to be virtual).
I think that if the method in OtherClass that you want to override in A and B is NOT virtual, then the override is not implicit.
I believe there's a way to Explicitly override the functions, look that up.
DeadMGs answer is of course correct. But, if you cannot change OtherClass Methode (e.g. it's from a third party lib) you might want to try this:
Are the pointers ptrA and ptrB of type OtherClass or AbstractClass in your lower example?
If they are OtherClass I would expect the behaviour you described. You could try casting the pointer to AbstractClass then:
dynamic_cast<AbstractClass*>(ptrA)->anyMethod();
As far as I can see from your code OtherClass::anyMethod() is not a virtual and already implemented. It should work as you described if you define it as virtual
I think that your declaration for the second case is:
OtherClass* ptrA; and not AbstractClass *ptrA;
if you declared like the first case , there's no problem because the method is virtual,but if you declare as OtherClass , the compiler will not find virtual and bind to the adress of this method without using vtble.
thanks for the answers.. helped me a lot to understand the problem.
In effect I posted some wrong code, because i was misunderstanding the real problem.
Anyway, i think i partially solved my problem.
Here's the code:
#include <iostream>
`` using namespace std;
class Other{
public:
void foo(){
cout << "Other\n";
}
void foo(int a){}
};
class Abstract : public Other{
public:
virtual void foo() {};
virtual void foo(int c){
Other::foo(c);
}
};
class A : public Abstract{
public:
void foo(){
cout << "A\n";
}
};
class B : public Abstract{
public:
void foo(){
cout << "B\n";
}
};
int main(){
cout << "main\n";
Abstract * ptrA = new A();
Abstract * ptrB = new B();
Other *o = new Other();
o->foo();
ptrA->foo();
ptrB->foo();
ptrB->foo(3); //can't no more use the method foo with different signatures implemented in the base class Other, unless I explicitly redefined in the class Abstract
dynamic_cast<Other*>(ptrB)->foo(3);//can't dynamic_cast from derived to base
I was making two errors:
In my real code (not the simplified version posted before) i forgot to declare virtual
the function foo()
Even declaring virtual wasn't enough. In fact all the implementations of that function must be wrapped inside the class Abstract to become visible to the subclasses A and b. Otherwise wont't compile.
I don't know if it could be a clean solution..in fact that way I need to wrap all foo method signatures.