Override public virtual function with private base function? - c++

Let's consider two classes A and B with the following interface:
class A {
public:
virtual void start() {} //default implementation does nothing
};
class B {
public:
void start() {/*do some stuff*/}
};
and then a third class which inherits from both, A publicly because it implements this "interface", and B privately because that's implementation detail.
However, in this specific implementation, start() only has to contain a call to B::start(). So I thought I could use a shortcut and do the following:
class C: public A, private B {
public:
using B::start;
};
and be done with it, but apparently it doesn't work. So I get using private base function doesn't work in order to override virtuals. From that, two questions:
Is there any way to make this work as I supposed it may have worked?
Why would the compiler accept this code as valid? As I see it there are now two start() functions with the exact same signature in C and yet the compiler seems fine with it and only calls A::start().
EDIT: A few precisions:
The goal is to manipulate C objects through A pointers.
I'm currently using a simple function that just calls B::start(), I was specifically wondering if a using declaration could indeed "override" a virtual, and if not, how this was allowed to have both functions coexist.
I might have omitted a few things like virtual inheritance for simplicity.

Is there any way to make this work as I supposed it may have worked?
You should override the member function and explicitly call B::start():
class C: public A, private B {
public:
void start() override { B::start(); }
};
Why would the compiler accept this code as valid? As I see it there
are now two start() functions with the exact same signature in C and
yet the compiler seems fine with it and only calls A::start().
You are right, there are two member functions accessible in C (A::start() and B::start()). And in class C, without overriding start() or making the start() of any of the base classes visible by doing a using ...::start(), you will have ambiguity error when trying to call the member function using unqalified namelookup from an object of C.
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Error, ambiguous
}
To fix that, you will have to use the qualified name such as:
C* c = new C();
c->A::start(); //Ok, calls A::start()
Now, doing a using B::start() in class C simply declares the start() to refer to B::start() whenever such name is used from an object of C
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
using B::start();
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Ok, calls B::start()
}
using B::start makes the function void B::start() visible in C, it does not override it. To call make all the above unqualified member function call, to call B::start(), you should override the member function in C, and make it call B::start()
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
void start() override { B::start(); }
};
int main(){
A* a = new C();
a->start(); //Ok, calls C::start() which in turn calls B::start()
// ^^^^^^^^^^^^^^^^ - by virtual dispatch
C* c = new C();
c->start(); //Ok, calls C::start() which in turn calls B::start()
}

Related

Create a new function which is not inherited from baseclass

Can I somehow create a new subclass method in C++ with the same name as a virtual one in base class, but stopping inheritance?
Let me explain it with some more details, consider this code:
#define L(m) std::cout << m << std::endl;
class A {
public:
virtual void func() { L("A::func"); };
virtual void func2() { L("A::func2"); };
};
class B: public A {
public:
void func() { L("B::func"); }; //implements A::func
void func2(){ L("B::func2"); }; //implements A::func2
};
class C: public A {
public:
void func2() { L("C::func2"); }; //implements A::func2
void func() { L("C::func"); }; //meant to declare a new function but accidentally overrides A::func
};
I don't want to declare func as final in A (I know it would stop inheritance, but I need that for class B).
Also I want to call C::func2 with A:
C c;
A* a = &c;
a->func2(); //must use C::func2 (standard inheritance)
a->func(); //must use A::func !!! (possible?)
c.func2(); //must use C::func2
c.func(); //must use C::func
Obviously I can rename C's func to something else but anyway, is this somehow achievable without completely abusing C++ norms?
Try this :
class C: public A {
public:
void func2() { L("C::func2"); };
void func(int i = 0) { L("C::func"); };
};
The C::func is hiding the A::func one with a different signature. I got this result :
C::func2
A::func
C::func2
C::func
Instead of this with your code :
C::func2
C::func
C::func2
C::func

Base class method alias

Let's consider the following code:
#include <iostream>
class Base
{
public:
void foo() //Here we have some method called foo.
{
std::cout << "Base::foo()\n";
}
};
class Derived : public Base
{
public:
void foo() //Here we override the Base::foo() with Derived::foo()
{
std::cout << "Derived::foo()\n";
}
};
int main()
{
Base *base1 = new Base;
Derived *der1 = new Derived;
base1->foo(); //Prints "Base::foo()"
der1->foo(); //Prints "Derived::foo()"
}
If I have the above stated classes, I can call the foo method from any of Base or Derived classes instances, depending on what ::foo() I need. But there is some kind of problem: what if I need the Derived class instance, but I do need to call the Base::foo() method from this instance?
The solve of this problem may be next:
I paste the next method to the class Derived
public:
void fooBase()
{
Base::foo();
}
and call Derived::fooBase() when I need Base::foo() method from Derived class instance.
The question is can I do this using using directive with something like this:
using Base::foo=fooBase; //I know this would not compile.
?
der1->Base::foo(); //Prints "Base::foo()"
You can call base class method using scope resolution to specify the function version and resolve the ambiguity which is useful when you don't want to use the default resolution.
Similar (Not exactly same case) example is mentioned # cppreference
struct B { virtual void foo(); };
struct D : B { void foo() override; };
int main()
{
D x;
B& b = x;
b.foo(); // calls D::foo (virtual dispatch)
b.B::foo(); // calls B::foo (static dispatch)
}

C++ protected member inheritance

My question is why I cannot call protected virtual member function in derived class through a pointer to the base class unless declaring derived class as a friend of base class?
For example:
#include <iostream>
class A {
friend class C; // (1)
protected:
virtual void foo() const = 0;
};
class B : public A {
void foo() const override { std::cout << "B::foo" << std::endl; }
};
class C : public A {
friend void bar(const C &);
public:
C(A *aa) : a(aa) { }
private:
void foo() const override {
a->foo(); // (2) Compile Error if we comment out (1)
//this->foo(); // (3) Compile OK, but this is not virtual call, and will cause infinite recursion
std::cout << "C::foo" << std::endl;
}
A *a;
};
void bar(const C &c) {
c.foo();
}
int main() {
B b;
C c(&b);
bar(c);
return 0;
}
The output is
B::foo
C::foo
In the above code, I want to call virtual function foo() through member a of class C (not the static bound one through this at compile time), but if I don't make C as A's friend, the call is illegal.
I think C is inherited from A, so that it can access the protected member of A, but why is it actually not happen?
Class C can access the protected members of its own base class, but not members of any other A.
In your example, the parameter a is part of the totally unrelated class B to which C has no access rights (unless you make it a friend).

Wrapper implementation for an abstract method in the base class

I have a base class inherited with many subclasses. I need to define a new signature for an abstract method, which is mostly a wrapper. I tried this
class B {
public:
virtual void f() = 0;
void f(string msg) { /* print msg and call f() */ }
};
class D : public B {
public:
void f() override { /* implementatation */}
};
int main() {
D d;
d.f("msg");
}
But it doesn't compile and give the following error
error: no matching function for call to 'D::f(string)
My questions are:
Why cannot D::f(string) be resolved?
Why does any of the following fix the problem?
renaming f(string) to f2(string) (ugly)
defining D::f(string x) { B::f(x)} (ugly as it has to be defined in every subclasses)
removing the abstract method, B::f() (not acceptable)
Any better solution?
The issue is that you hid B::f(std::string) here:
class D : public B {
public:
void f() override;
};
When you call D.f("msg"), name lookup will find the one f() in D and stop looking. We first find the candidate functions then perform overload resolution. Since that one happens to take no arguments, you get the compile error.
If you want to use the other overload of f, you need to bring it into D as well, like so:
class D : public B {
public:
using B::f;
void f() override;
};
Now we have D::f() (the overridden virtual function) and D::f(std::string ) (which we brought in from B).
An alternative, trivial solution would be to simply rename one or the other function so you don't have this problem to begin with.
Are you using the NVI idoims? Such as:
class B {
public:
virtual void f() = 0;
void f(string msg) {
/* print msg and call f() */
std::cout << msg;
f();
}
virtual ~B() {}
};
Then you should as far as possible try to call the non-virtual member function from the base class (by reference or pointer), such as:
D d;
B& b = d;
b.f("msg");

Private function member called outside of class

In the example below, why is B::f() called even though it is private?
I know this fact that :
Access is checked at the call point using the type of the expression used to denote the object for which the member function is called.
#include <iostream>
class A {
public:
virtual void f() { std::cout << "virtual_function"; }
};
class B : public A {
private:
void f() { std::cout << "private_function"; }
};
void C(A &g) { g.f(); }
int main() {
B b;
C(b);
}
Because the standard says so:
[C++11: 11.5/1]: The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [ Example:
class B {
public:
virtual int f();
};
class D : public B {
private:
int f();
};
void f() {
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public,
// D::f() is invoked
pd->f(); // error: D::f() is private
}
—end example ]
The example is the same as yours, lol.
private functions can override public virtual functions from a base class. Accessability is, in a fact, completely ignored when determining whether a function overrides another, so even in
// Redundant private for clarity:
class A { private: virtual void foo(); };
class B : A { public: void foo(); };
B::foo overrides A::foo.
During compile time C++ compiler verifies accessibility of functions and methods based on their type. In function C variable g is of type A (checked during compilation of the code), in which method f is declared as public.
Take a look at this link