struct A{
virtual void fun(){cout<<"A";}
};
struct B:public A{
void fun(){cout<<"B";}
};
struct C:public B{
void fun(){cout<<"C";}
};
int main()
{
C c;B b1;
A *a=&b1;
a->fun(); //1
B *b=&c;
b->fun(); //2
return 0;
}
In the above code B::fun() is getting converted to virtual function implicitly as I have made A::fun() virtual. Can I stop this conversion?
If not possible what are the alternatives to make the above code print "BB" ?
A virtual function is virtual in all derived classes. There is no way to prevent this.
(§10.3/2 C++11) If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf. For convenience we say that any virtual function overrides itself.
However, if you'd like to use the function that corresponds to the static, rather than the dynamic, type of a pointer (i.e., in your example, B::fun instead of C::fun, given that the pointer is declared as B*), then you can, at least in C++11, use the alias definition below to get access to the static (=compile-time) type:
template <typename Ptr>
using static_type = typename std::remove_pointer<Ptr>::type;
This is how you'd use this in main() (or anywhere else):
int main()
{
C c; B b1;
A *a = &b1;
a->fun();
B *b = &c;
/* This will output 'B': */
b->static_type<decltype(b)>::fun();
return 0;
}
If you do not want your derived classes to override the function then there is no reason why you should mark it virtual in base class. The very basis of marking a function virtual is to have polymorphic behavior through derived class function overidding.
Good Read:
When to mark a function in C++ as a virtual?
If you want your code to guard you against accidental overidding in derived classes.You can use the final specifier in C++11.
Yes, if you want to explicitly call a function in a specific class you can use a fully qualified name.
b->A::fun();
This will call the version of fun() belonging to A.
The following achieves the observable behaviour you're asking for. In A, non-virtual fun() run virtual fun_() so the behaviour can be customised in B, but anyone calling fun() on a derived class will only see the non-polymorphic version.
#include <iostream>
using namespace std;
struct A{
void fun(){fun_();}
private:
virtual void fun_() { cout << "A\n"; }
};
struct B:public A{
void fun(){cout<<"B\n";}
private:
virtual void fun_() final { fun(); }
};
struct C:public B{
void fun(){cout<<"C\n";}
};
int main()
{
C c;B b1;
A *a=&b1;
a->fun(); //1
B *b=&c;
b->fun(); //2
c.fun(); // notice that this outputs "C" which I think is what you want
}
If using C++03, you can simply leave out the "final" keyword - it's only there to guard against further unwanted overrides of the virtual behaviour in B-derived classes such as C.
(You might find it interesting to contrast this with the "Nonvirtual Interface pattern" - see C++ Coding Standards by Sutter and Alexandrescu, point 39)
Discussion
A having fun virtual implies that overriding it in derived classes is a necessary customisation ability for derived classes, but at some point in the derivation hierarchy the choice of implementation behaviours might have narrowed down to 1 and providing a final implementation's not unreasonable.
My real concern is that you hide A/B's fun() with C::fun... that's troubling as if they do different things then your code could be very hard to reason about or debug. B's decision to finalise the virtual function implies certainty that there's no need for such further customisation. Code working from A*/A&/B*/B& will do one thing, while wherever a C object's type is statically known, the behaviour may differ. Templated code is one place where C::fun may easily be called without the template author or user being very conscious of it. To assess whether this is a genuine hazard for you, it would help to know what the functional purpose of "fun" is and how implementation might differ between A, B and C....
If you declare the function in B like this
void fun(int ignored=0);
it will become an overload which will not take part in resolving virtual calls. Beware that calling a->fun() will call A::fun() though even if a actually refers to a B, so I would strongly advise against this approach as it makes things even more confusing than necessary.
Question is: What exactly is it that you want to achieve or avoid? Knowing that, people here could suggest a better approach.
Related
Consider the example:
#include <iostream>
class A {
public:
virtual void f();
};
void A::f()
{
std::cout << "f() from A\n";
}
class B: public A {
public:
virtual void f() = 0;
};
class C: public B {
public:
void f();
};
void C::f()
{
std::cout << "f() from C\n";
}
int main()
{
C o;
o.f();
}
A::f() implementation is "hidden" from class C, which provides its own implementation for f() - effectively making A::f() more or less pointless. I see little value in such class hierarchy design, but my question whether this is a valid C++ or just "works" (such as undefined behaviours)?
It is clearly allowed and supported by the standard (cf, for example, this online C++ standard draft), and thus clearly not undefined behaviour:
10.4 Abstract classes
5 [ Note: An abstract class can be derived from a class that is not
abstract, and a pure virtual function may override a virtual function
which is not pure. — end note ]
The effect is that your class B becomes abstract and any subclass - if it shall not be abstract, too - must define f() then; the implementation in class A can still be invoked through A::f(), such that it is - from the perspective of reusing the implementation - not pointless.
This will safely achieve the goal of requiring the author of C to provide an implementation for f().
I would query why this is needed — if the base implementation is not "valid" in your design then why does it exist, and/or why is it virtual?
They can still invoke A::f(), anyway, so whether this can be deemed "hiding" is open to debate.
This is valid and well-defined C++.
It can occasionally be useful if you want to force a user of your class to implement a method that's already implemented in a base class (and don't want to use a different name which would be a more obvious choice). GUI libraries implementing operating system message pumps are one application.
my question whether this is a valid C++ or just "works" (such as undefined behaviours)?
The behaviour of the program is well defined.
effectively making A::f() more or less pointless.
Of course, if you never call a function, then defining the function is unnecessary indeed. To clarify, the function would have to be declared pure virtual if you did choose to omit the definition (the opposite is not true; you can define a pure virtual function).
As far as I can see there's no undefined behavior = 0 only means that derived classes must override it. But you can still provide an out-of-line definition for that function in the same class.
In this code, I have defined three structs, base, derived and MoreDerived each inheriting from the previous member in the list.
However, I have defined the function f() to be virtual in the derived
struct, NOT in the base struct.
#include <iostream>
struct base {
void f() {
std::cout << "base\n";
}
};
struct derived : base {
virtual void f() {
std::cout << "derived\n";
}
};
struct morederived : derived {
void f() {
std::cout << "more derived\n";
}
};
int main()
{
derived d;
morederived md;
base* dp = &d;
base* mdp = &md;
dp->f();
mdp->f();
}
The code above prints base \n base as expected. And if I declare dp and mdp to be pointers of type derived*, the code prints derived \n more derived as expected again, since f is defined to be virtual in the derived.
Of course, this code is small and so the results are predictable. But in large code bases, is doing the above ever a good idea?
Note: I have not seen this in any codes yet, in my limited c++ experience, nor do I have any plans to use such a pattern (or anti-pattern :-D). I am asking this purely out of curiosity.
EDIT: I don't feel this question is not a duplicate to the one pointed out. I am not asking if the virtual keyword is necessary in a derived class. I am asking the effects/plusses/minuses of placing the virtual keyword on a function f() that has an implementation in the base class, but is declared virtual only in the derived class, and then is inherited by other classes.
Specifically I am asking if this thing is a patter or anti-pattern.
Yes, this breaks the Is-a contract. Your derived is not playing by the same rules as base.
This is never a good idea. You might want to consider composition for derived. I.e.
struct derived {
base b; // for whatever use you might have for base.
virtual void f() {
std::cout << "derived\n";
}
};
In my book, it qualifies as a code smell.
derived::f() actually hides base::f() rather than overriding it.
This means that base_ptr->f() always calls base::f(), even if base_ptr points at an instance of a derived class, whereas derived_ptr->f() will use virtual function dispatch.
The fact of making derived::f() virtual and documenting that it can be overridden, encourages implementers of classes like morederived to expect that a call of the form pointer->f(), if pointer points at an instance of morederived, to believe their version will be called. In reality, which version will be called depends on the type of pointer (e.g. different version called if it is base * or derived *).
That can result in quite an unpleasant surprise for anyone who uses the classes, and doesn't closely inspect all classes in the hierarchy. In large class hierarchies, particularly if provided by someone else, developers will not typically inspect a complete class hierarchy provided by someone else that closely. The will assume it works as advertised, if they care at all about their productivity.
If this sort of thing was present in a commercial class library, the vendor could expect to receive bug reports from customers bitten by such a bug, to lose customers of their library (on the premise that they introduced a bug through bad development technique), or both.
I've seen it stated that C++ has name hiding for the purposes of reducing the fragile base class problem. However, I definitely don't see how this helps. If the base class introduces a function or overload that previously did not exist, it might conflict with those introduced by the derived class, or unqualified calls to global functions or member functions- but what I don't see is how this is different for overloads. Why should overloads of virtual functions be treated differently to, well, any other function?
Edit: Let me show you a little more what I'm talking about.
struct base {
virtual void foo();
virtual void foo(int);
virtual void bar();
virtual ~base();
};
struct derived : base {
virtual void foo();
};
int main() {
derived d;
d.foo(1); // Error- foo(int) is hidden
d.bar(); // Fine- calls base::bar()
}
Here, foo(int) is treated differently to bar(), because it's an overload.
I'll assume that by "fragile base class", you mean a situation where changes to the base class can break code that uses derived classes (that being the definition I found on Wikipedia). I'm not sure what virtual functions have to do with this, but I can explain how hiding helps avoid this problem. Consider the following:
struct A {};
struct B : public A
{
void f(float);
};
void do_stuff()
{
B b;
b.f(3);
}
The function call in do_stuff calls B::f(float).
Now suppose someone modifies the base class, and adds a function void f(int);. Without hiding, this would be a better match for the function argument in main; you've either changed the behaviour of do_stuff (if the new function is public), or caused a compile error (if it's private), without changing either do_stuff or any of its direct dependencies. With hiding, you haven't changed the behaviour, and such breakage is only possible if you explicitly disable hiding with a using declaration.
I don't think that overloads of virtual functions are treated any differently that overloads of regular functions. There might be one side effect though.
Suppose we have a 3 layers hierarchy:
struct Base {};
struct Derived: Base { void foo(int i); };
struct Top: Derived { void foo(int i); }; // hides Derived::foo
When I write:
void bar(Derived& d) { d.foo(3); }
the call is statically resolved to Derived::foo, whatever the true (runtime) type that d may have.
However, if I then introduce virtual void foo(int i); in Base, then everything changes. Suddenly Derived::foo and Top::foo become overrides, instead of mere overload that hid the name in their respective base class.
This means that d.foo(3); is now resolved statically not directly to a method call, but to a virtual dispatch.
Therefore Top top; bar(top) will call Top::foo (via virtual dispatch), where it previously called Derived::foo.
It might not be desirable. It could be fixed by explicitly qualifying the call d.Derived::foo(3);, but it sure is an unfortunate side effect.
Of course, it is primarily a design problem. It will only happen if the signature are compatible, else we'll have name hiding, and no override; therefore one could argue that having "potential" overrides for non-virtual functions is inviting troubles anyway (dunno if any warning exist for this, it could warrant one, to prevent being put in such a situation).
Note: if we remove Top, then it is perfectly fine to introduce the new virtual method, since all old calls were already handled by Derived::foo anyway, and thus only new code may be impacted
It is something to keep in mind though when introducing new virtual methods in a base class, especially when the impacted code is unknown (libraries delivered to clients).
Note that C++0x has the override attribute to check that a method is truly an override of a base virtual; while it does not solve the immediate problem, in the future we might imagine compilers having a warning for "accidental" overrides (ie, overrides not marked as such) in which case such an issue could be caught at compile-time after the introduction of the virtual method.
In The Design and Evolution of C++, Bjarne Stroustrup Addison-Weslay, 1994 section 3.5.3 pp 77, 78, B.S. explains that the rule by which a name in a derived class hides all definition of the same name in its base classes is old and dates back from C with Classes. When it was introduced, B.S. considered it as the obvious consequence of scoping rules (it's the same for nested blocks of code or nested namespaces — even if namespace were introduced after). The desirability of its interactions with overloading rules (the overloaded set doesn't contain the function defined in the base classes, nor in the enclosing blocks — now harmless as declaring functions in block is old fashioned —, nor in enclosing namespaces where the problem occasionally strikes as well) has been debated, to the point that G++ implemented alternative rules allowing the overloading, and B.S. argued that the current rule helps preventing errors in situations like (inspired from real live problems with g++)
class X {
int x;
public:
virtual void copy(X* p) { x = p->x; }
};
class XX: public X {
int xx;
public:
virtual void copy(XX* p) { xx = p->xx; X::copy(p); }
};
void f(X a, XX b)
{
a.copy(&b); // ok: copy X part of b
b.copy(&a); // error: copy(X*) is hidden by copy(XX*)
}
Then B.S. continues
In retrospect, I suspect that the overloading rules introduced in 2.0 might have been able to handle this case. Consider the call b.copy(&a). The variable b is an exact type match for the implicit argument of XX::copy, but requires a standard conversion to match X::copy. The variable a on the other hand, is an exact match for the explicit argument of X::copy, but requires a standard conversion to match XX:copy. Thus, had the overloading been allowed, the call would have been an error because it is ambiguous.
But I fail to see where the ambiguity is. It seems to me that B.S. overlooked the fact that &a can't be implicitly converted to a XX* and thus only X::copy has be considered.
Indeed trying with free (friends) functions
void copy(X* t, X* p) { t->x = p->x; }
void copy(XX* t, XX* p) { t-xx = p->xx; copy((X*)t, (X*)p); }
I get no ambiguity error with current compilers and I don't see how rules in the Annotated C++ Reference Manual would makes a difference here.
With the struct definition given below...
struct A {
virtual void hello() = 0;
};
Approach #1:
struct B : public A {
virtual void hello() { ... }
};
Approach #2:
struct B : public A {
void hello() { ... }
};
Is there any difference between these two ways to override the hello function?
They are exactly the same. There is no difference between them other than that the first approach requires more typing and is potentially clearer.
The 'virtualness' of a function is propagated implicitly, however at least one compiler I use will generate a warning if the virtual keyword is not used explicitly, so you may want to use it if only to keep the compiler quiet.
From a purely stylistic point-of-view, including the virtual keyword clearly 'advertises' the fact to the user that the function is virtual. This will be important to anyone further sub-classing B without having to check A's definition. For deep class hierarchies, this becomes especially important.
The virtual keyword is not necessary in the derived class. Here's the supporting documentation, from the C++ Draft Standard (N3337) (emphasis mine):
10.3 Virtual functions
2 If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
No, the virtual keyword on derived classes' virtual function overrides is not required. But it is worth mentioning a related pitfall: a failure to override a virtual function.
The failure to override occurs if you intend to override a virtual function in a derived class, but make an error in the signature so that it declares a new and different virtual function. This function may be an overload of the base class function, or it might differ in name. Whether or not you use the virtual keyword in the derived class function declaration, the compiler would not be able to tell that you intended to override a function from a base class.
This pitfall is, however, thankfully addressed by the C++11 explicit override language feature, which allows the source code to clearly specify that a member function is intended to override a base class function:
struct Base {
virtual void some_func(float);
};
struct Derived : Base {
virtual void some_func(int) override; // ill-formed - doesn't override a base class method
};
The compiler will issue a compile-time error and the programming error will be immediately obvious (perhaps the function in Derived should have taken a float as the argument).
Refer to WP:C++11.
Adding the "virtual" keyword is good practice as it improves readability , but it is not necessary. Functions declared virtual in the base class, and having the same signature in the derived classes are considered "virtual" by default.
There is no difference for the compiler, when you write the virtual in the derived class or omit it.
But you need to look at the base class to get this information. Therfore I would recommend to add the virtual keyword also in the derived class, if you want to show to the human that this function is virtual.
The virtual keyword should be added to functions of a base class to make them overridable. In your example, struct A is the base class. virtual means nothing for using those functions in a derived class. However, it you want your derived class to also be a base class itself, and you want that function to be overridable, then you would have to put the virtual there.
struct B : public A {
virtual void hello() { ... }
};
struct C : public B {
void hello() { ... }
};
Here C inherits from B, so B is not the base class (it is also a derived class), and C is the derived class.
The inheritance diagram looks like this:
A
^
|
B
^
|
C
So you should put the virtual in front of functions inside of potential base classes which may have children. virtual allows your children to override your functions. There is nothing wrong with putting the virtual in front of functions inside of the derived classes, but it is not required. It is recommended though, because if someone would want to inherit from your derived class, they would not be pleased that the method overriding doesn't work as expected.
So put virtual in front of functions in all classes involved in inheritance, unless you know for sure that the class will not have any children who would need to override the functions of the base class. It is good practice.
There's a considerable difference when you have templates and start taking base class(es) as template parameter(s):
struct None {};
template<typename... Interfaces>
struct B : public Interfaces
{
void hello() { ... }
};
struct A {
virtual void hello() = 0;
};
template<typename... Interfaces>
void t_hello(const B<Interfaces...>& b) // different code generated for each set of interfaces (a vtable-based clever compiler might reduce this to 2); both t_hello and b.hello() might be inlined properly
{
b.hello(); // indirect, non-virtual call
}
void hello(const A& a)
{
a.hello(); // Indirect virtual call, inlining is impossible in general
}
int main()
{
B<None> b; // Ok, no vtable generated, empty base class optimization works, sizeof(b) == 1 usually
B<None>* pb = &b;
B<None>& rb = b;
b.hello(); // direct call
pb->hello(); // pb-relative non-virtual call (1 redirection)
rb->hello(); // non-virtual call (1 redirection unless optimized out)
t_hello(b); // works as expected, one redirection
// hello(b); // compile-time error
B<A> ba; // Ok, vtable generated, sizeof(b) >= sizeof(void*)
B<None>* pba = &ba;
B<None>& rba = ba;
ba.hello(); // still can be a direct call, exact type of ba is deducible
pba->hello(); // pba-relative virtual call (usually 3 redirections)
rba->hello(); // rba-relative virtual call (usually 3 redirections unless optimized out to 2)
//t_hello(b); // compile-time error (unless you add support for const A& in t_hello as well)
hello(ba);
}
The fun part of it is that you can now define interface and non-interface functions later to defining classes. That is useful for interworking interfaces between libraries (don't rely on this as a standard design process of a single library). It costs you nothing to allow this for all of your classes - you might even typedef B to something if you'd like.
Note that, if you do this, you might want to declare copy / move constructors as templates, too: allowing to construct from different interfaces allows you to 'cast' between different B<> types.
It's questionable whether you should add support for const A& in t_hello(). The usual reason for this rewrite is to move away from inheritance-based specialization to template-based one, mostly for performance reasons. If you continue to support the old interface, you can hardly detect (or deter from) old usage.
I will certainly include the Virtual keyword for the child class, because
i. Readability.
ii. This child class my be derived further down, you don't want the constructor of the further derived class to call this virtual function.
#include<iostream>
using namespace std;
class A
{
int a;
int b;
public:
void eat()
{
cout<<"A::eat()"<<endl;
}
};
class B: public A
{
public:
void eat()
{
cout<<"B::eat()"<<endl;
}
};
class C: public A
{
public:
void eat()
{
cout<<"C::eat()"<<endl;
}
};
class D: public B, C
{
};
int foo(A *ptr)
{
ptr->eat();
}
main()
{
D obj;
foo(&(obj.B)); //error. How do i call with D's B part.
}
The above foo call is a compile time error.
I want to call foo with obj's B part without using virtual inheritance. How do i do that.
Also, in case of virtual inheritance, why the offset information need to be stored in the vtable. This can be determined at the compile time itself. In the above case, if we pass foo with D's object, at compile time only we can calculate the offset of D's A part.
Inheriting twice
With double inheritance you have an ambiguity - the compiler cannot know which of the two A bases do you want to use. If you want to have two A bases (sometimes you may want to do this), you may select between them by casting to B or C. The most appropriate from default casts here is the static_cast (as the weakest available), however it is not realy needed (it is still stronger than your case needs), as you are not casting to a derived type. A custom safe_cast template should do the job:
/// cast using implicit conversions only
template <class To,class From>
inline To safe_cast( const From &from ) {return from;}
main()
{
D obj;
foo(safe_cast<B *>(&obj)); //error. How do i call with D's B part.
}
Compile time types - use templates
Also, in case of virtual inheritance,
why the offset information need to be
stored in the vtable. This can be
determined at the compile time itself.
In the above case, if we pass foo with
D's object, at compile time only we
can calculate the offset of D's A
part.
This is a misconception. The foo function as it is written now has no compile type information about ptr type other than it is A *, even if you pass B * or C*. If you want foo to be able to act based on the type passed compile time, you need to use templates:
template <class TypeDerivedFromA>
int foo(TypeDerivedFromA *ptr)
{
ptr->eat();
}
Virtual Inheritance
Your questions mentions virtual inheritance. If you want to use virtual inheritance, you need to specify so:
class B: public virtual A ...
class C: public virtual A ...
With this the code would compile, but with this solution there is no way you could select between B::A or C::A (there is only one A), therefore this is probably not what you are about.
Virtual functions
Furthermore, your questions seems to be confusing two different concepts, virtual inheritance (which means sharing one base class between two intermediate base classes) and virtual functions (which mean allowing derived class function to be called via base class pointer). If you want the B::eat to be called using A pointer, you can do this without virtual inheritance (actually virtual inheritance would prevent you doing so, as explained above), using virtual functions:
class A
{
int a;
int b;
public:
virtual void eat()
{
cout<<"A::eat()"<<endl;
}
};
If virtual functions are not acceptable for you, the compile time mechanism for this are templates, as explained above.
Use a cast - static_cast is required here to cast up the heirarchy.
main()
{
D obj;
foo(static_cast<B*>(&obj));
}
First of all, obj does not have a member named B. It Inherits from B, which means that it inherits all of B's members as its own.
You can call:
foo(static_cast<B*>(&obj)); to make it work.
I don't think the static_cast will work.
When you are on the foo function, all the compiler knows is that you have a pointer to A, whatever the type you passed as parameter.
If you don't use virtual inheritance, then I think there is no way to call a B function from a pointer to A.