I have four classes (classic diamond problem in C++). Let's call the grandparent class A, the parent classes B and C and the child class D. Both B and C have a public member function called attack. I want D to use B's attack function. Class D looks like this:
class D : public B, public C
{
using B::attack;
public:
D(void);
D(std::string &name);
D(D &instance);
~D(void);
D& operator=(D &instance);
};
The attack function simply displays a message on the standard output.
My main looks like this:
int main(void)
{
DiamondTrap dt;
dt.attack();
}
The error I get is the following:
error: 'attack' is a private member of 'D'
note: implicitly declared private here
using B::attack;
Does this mean that using using keyword makes member functions private? I don't know why attack is now private. I can call attack it in my main function from an instance of B, but not from an instance of D. I wish to call it from an instance of D. How can I solve this?
Note I don't know if this is relevant to my problem, but B and C's inheritance is virtual, so only one instance of A is created when an instance of D is created. Also, I am not allowed to use friend keyword in my solution, and I am only allowed to use C++98.
Related
If B inherits from A using public, can B override one of the functions and force it to be private?
class A
{
public:
virtual double my_func1(int i);
virtual double my_func2(int i);
}
class B : public A // Notice the public inheritance
{
public:
virtual double my_func1(int i);
private:
virtual double my_func2(int i);
}
How about the other way around? if the inheritance type is private - can B force a specific function to be public?
What if A is pure abstract? does it make a difference?
Would protected make any difference in any combination?
If B inherits from A using public, can B override one of the functions and force it to be private?
NO
Eventhough the my_func1() is declared under priavte access specifier it can be still called through a pointer to class A, actually pointing to a object of class B
The call to my_func1() is evaluated at run time depending on the type of objected pointed by the pointer. At compile time the compile sees the my_func1() call as call to A::my_func1() and since A::my_func1() is public the compiler doesn't report only error. It is only at runtime that actual function call B::my_func1() is evaluated.
Ofcourse, You cannot directly call my_func1() through object of class B though because B::my_func1() is declared under Private Access specifier and You cannot access privately declared members from outside the class.
How about the other way around? if the inheritance type is private - can B force a specific function to be public?
NO
If you are calling my_func1() through a pointer of the Base class A, At compile time it is just evaluated as call to A::my_func1() which is Invalid since A::my_func1() is declared private inclass A`
What if A is pure abstract? does it make a difference?
NO
It makes no difference if the base class is Abstract or just polymorphic. Same rules will be applicable.
Would protected make any difference in any combination?
NO
As explained in first 2 Q's if you are calling a virtual function thorough pointer to Base class then at compile time the compiler only checks the access of that member function in Base class because compiler sees it as call to Base class member function. The actual call to the function is evaluated at run time and the feature is called Runtime Polymorphism or Dynamic polymorphism which is independent of the Access specifiers, which as a compile time construct.
So in conclusion,
overriding members of Base Class does not affect access
Difference
What if A is pure abstract? does it make a difference?
The only difference it makes is the following, i.e how they can (or cannot) be used:
A *pa = new B();
pa->my_func2(10); //calls B::my_func2() even though its private!
B *pb = new B();
pb->my_func2(10); //compilation error - trying to access private function
Explanation
Access-specifiers are compile-time construct, and so, the compiler detects any violation of access-rules at compile-time (obviously) based on the static type of the object (or pointer). Such violation cannot be detected at runtime.
So pa->my_func2() works, because the compiler sees that the static type of pa is A* which has a public function my_func2() defined, so the expression pa->my_func2() passes the compiler's test. Hence it works.
But pb->my_func2() doesn't work, since the static type of pb is B* which has a private function my_func2(), hence the code wouldn't even compile!
==> If B inherits from A using public, can B override one of the functions and force it to be private?
NO. Pointer/reference to A will always see my_func2 as public. You can still call this method using A* or A&. (what you ask is possible in Java).
==> if the inheritance type is private - can B force a specific function to be public?
At 1st place if the inheritance type is private/protected then you can NOT assign object of Derived class to Base class pointer/reference. e.g. you can not do following!!
A* p = new B; // error
==> What if A is pure abstract? does it make a difference?
NO difference (except you have to define methods in B)
==> Would protected make any difference in any combination?
NO difference (with respect to Base class)
I was going through posts made by others and found explanation related to errors encountered when inheritance being private/protected in Derived class somewhat confusing/incomplete.
Consider below code snippet,
class A
{
public:
virtual double my_func1(int i);
virtual double my_func2(int i);
}
class B : private A // Notice private inheritance
{
public:
virtual double my_func1(int i);
private:
virtual double my_func2(int i);
}
A* ptr = new B; // this is not legal because B has a private base
ptr->my_func1(); // my_func1() is not accessible
ptr->my_func2(); // my_func2() is also not accessible not because it is private but due
// base class A being inherited privately
So when we inherit class B from class A using private/protected specifiers then it means that nobody in outside world knows that class B has inherited from class A hence it's illegal to assign pointer/reference of type class B to pointer/reference of type class A. Hence, access of private/protected overridden virtual function in derived classes is only valid when inheritance in public.
What you override does not affect access. So you can create public override of privately inherited function exactly the same way you create private override of publicly inherited function.
The public override of the privately inherited function obviously has to call the real function and it should be inline, so the compiler will optimize it away.
Suppose I have two classes A and B.
Class A is subclass of X with virtual method known as now_do() so I can easily override it with class A. However most issues are in class B, so I want to include class A in B and override now_do() as A::now_do(){...} but its not possible, So how can I do in order to use variables of class B inside A::now_do(){}.
Code example (class B):
#include "A.cpp"
class B{
public:
int a;
//....
void A::now_do(){
cout<<a<<endl; //Access a member of this class B.
}
};
//But it works when I put outside B class
//However now I can't access members of class B.
void A::now_do(){
cout<<a<<endl; //Can't access a member of this class B.
}
Error I get is: You cannot define member function A::now_do() within B.
Indeed, you can't do what you were trying to do in C++ (nor in any other language, I would think): You see, classes A and B don't share instance information. When you instantiate an A, there is no associated instance of B from which you could take an a value. Nor can you "stick" your a from a B instance into an A instance.
If you want to associate instances of A and B, you will probably want to:
Have a
class AWithB { A instance_of_A; B instance_of_B; };
(that's not a good choice of names of course...)
Make the now_do() a method of AWithB, so it can access both information specific to the A instance and to the B instance
Another alternative would be for class B to inherit from A, and then it could override now_do().
I am just confused about the tiny program on inheritance below:
#include<iostream>
using namespace std;
struct B {
virtual int f() { return 1; }
}; // f is public in B
class D : public B {
int f() { return 2; }
}; // f is private in D
int main()
{
D d;
B& b = d;
cout<<b.f()<<endl; // OK: B::f() is public, D::f() is invoked even though it's private
cout<<d.f()<<endl; // error: D::f() is private
}
I can't figure out why D::f() is private, D is public inherited from B, so the public function f in B
is also public in D (I know without inheritance, member access is private by default)
f is a virtual function in B, so if we call b.f(), we actually call D::f(), but just as the illustration mentioned, why D::f() is able to be invoked even though it's private?
Can anyone explain the simple inheritance problem in detail?
This has to do that with virtual dispatch is a runtime concept. The class B doesn't care which class extends it, and it doesn't care if it's private or public because it can't know.
I can't figure out why D::f() is private, D is public inherited from B, so the public function f in B
is also public in D(I know without inheritance, member access is private by default)
D::f() is private because you made it private. This rule isn't affect by inheritance nor virtual dispatch.
f is a virtual function in B, so if we call b.f(), we actually call D::f(), but just as the illustration mentioned, why D::f() is able to be invoked even though it's private?
Because in reality, when invoking b.f(), the compiler has no idea which function will actually be called. It will simply call the function f(), and since B::f is virtual, the called function will be chosen at runtime. The runtime program has no information about which function is private or protected. It only know functions.
If the function is chosen at runtime, the compiler can't know at compile-time what function will be called, and the access specifier can't be known. In fact, the compiler won't even try to check if the function called will be private or not. The access specifier could be in some code that the compiler haven't seen yet.
As you've experienced, you can't call D::f directly. This is exactly what private will do: prohibit direct access of the member. You can, however, access it indirectly through a pointer or a reference. The virtual dispatch you use will do that internally.
Access specifiers apply to the function name only, they aren't some restriction on how or when the function can be called by other means. A private function could be called outside the class if it is made available by some means other than its name (for example, a function pointer).
For a class declared with class keyword, the default access-specifier is private. Your code is the same as:
// ...
class D: public B
{
private:
int f() { return 2; }
};
As you can see, f is private in D. It makes no difference what the access specifier was of any function in B with the same name. Be clear in your mind that B::f() and D::f() are two different functions.
The effect of the virtual keyword is that if f() without a scope qualifier is called on a B reference that refers to a D object, then even though it resolves to B::f(), actually D::f() is invoked instead.
This process still uses the access specifier for B::f(): access is checked at compile-time; but it might be run-time matter as to which function is called.
The C++ Standard has an exact example of this:
11.5 Access to virtual functions [class.access.virt]
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]
Can't explain it any clearer.
The answer given illustrates what is being done, but why would you ever want to do this, where the base class calls private virtual functions?
Well, there is a design pattern called the template method pattern that uses this technique of having a base class that calls private virtual functions in the derived class.
struct B
{
virtual ~B() {};
int do_some_algorithm()
{
do_step_1();
do_step_2();
do_step_3();
}
private:
virtual void do_step_1() {}
virtual void do_step_2() {}
virtual void do_step_3() {}
};
class D : public B
{
void do_step_1()
{
// custom implementation
}
void do_step_2()
{
// custom implementation
}
void do_step_3()
{
// custom implementation
}
};
int main()
{
D dInstance;
B * pB = &dInstance;
pB->do_some_algorithm();
}
This allows us to not expose the custom steps of class D to the public interface, but at the same time allows B to call these functions using a public function.
This actually has less to do with virtual dispatch and more to do with what access specifiers mean.
The function itself is not private; its name is.
Consequently, the function cannot be named outside of the scope of the class, e.g. from main. However, you can still do so through a name that is public (i.e. the base's virtual function that is overridden) or from a scope in which the function's name is accessible despite the private qualifier (e.g. a member function of that class).
That's just how it works.
why D::f() is able to be invoked even though it's private?
To understand virtual function mechanism it is good to know, how it is usually implemented. A function at runtime is actually no more than an address in memory where the executable code of the function body locates. To call the function we need to know its address (a pointer). C++ object with virtual functions representation in memory contains so called vtable - an array of pointers to the virtual functions.
Key point is that in derived classes vtable repeats (and may extend) the vtable of base class, but if the virtual function is overriden its pointer is replaced in derived object's vtable.
When a virtual function call is done through the base class pointer, the address of the virtual function is calculated as an offset in the vtable array. No other checks are done, just the function address is taken.
If it is a base class object, it will be the address of the base class function. If it is a derived class object, it will be the address of the derived class function, does not matter if it was declared private or not.
This how it works.
Member of struct is default to be public, and member of class is default to be private.
So f() in B is public and when it's derived to D, because you didn't explicitly declare it is public, so according to rules of derivation, it became private.
If B inherits from A using public, can B override one of the functions and force it to be private?
class A
{
public:
virtual double my_func1(int i);
virtual double my_func2(int i);
}
class B : public A // Notice the public inheritance
{
public:
virtual double my_func1(int i);
private:
virtual double my_func2(int i);
}
How about the other way around? if the inheritance type is private - can B force a specific function to be public?
What if A is pure abstract? does it make a difference?
Would protected make any difference in any combination?
If B inherits from A using public, can B override one of the functions and force it to be private?
NO
Eventhough the my_func1() is declared under priavte access specifier it can be still called through a pointer to class A, actually pointing to a object of class B
The call to my_func1() is evaluated at run time depending on the type of objected pointed by the pointer. At compile time the compile sees the my_func1() call as call to A::my_func1() and since A::my_func1() is public the compiler doesn't report only error. It is only at runtime that actual function call B::my_func1() is evaluated.
Ofcourse, You cannot directly call my_func1() through object of class B though because B::my_func1() is declared under Private Access specifier and You cannot access privately declared members from outside the class.
How about the other way around? if the inheritance type is private - can B force a specific function to be public?
NO
If you are calling my_func1() through a pointer of the Base class A, At compile time it is just evaluated as call to A::my_func1() which is Invalid since A::my_func1() is declared private inclass A`
What if A is pure abstract? does it make a difference?
NO
It makes no difference if the base class is Abstract or just polymorphic. Same rules will be applicable.
Would protected make any difference in any combination?
NO
As explained in first 2 Q's if you are calling a virtual function thorough pointer to Base class then at compile time the compiler only checks the access of that member function in Base class because compiler sees it as call to Base class member function. The actual call to the function is evaluated at run time and the feature is called Runtime Polymorphism or Dynamic polymorphism which is independent of the Access specifiers, which as a compile time construct.
So in conclusion,
overriding members of Base Class does not affect access
Difference
What if A is pure abstract? does it make a difference?
The only difference it makes is the following, i.e how they can (or cannot) be used:
A *pa = new B();
pa->my_func2(10); //calls B::my_func2() even though its private!
B *pb = new B();
pb->my_func2(10); //compilation error - trying to access private function
Explanation
Access-specifiers are compile-time construct, and so, the compiler detects any violation of access-rules at compile-time (obviously) based on the static type of the object (or pointer). Such violation cannot be detected at runtime.
So pa->my_func2() works, because the compiler sees that the static type of pa is A* which has a public function my_func2() defined, so the expression pa->my_func2() passes the compiler's test. Hence it works.
But pb->my_func2() doesn't work, since the static type of pb is B* which has a private function my_func2(), hence the code wouldn't even compile!
==> If B inherits from A using public, can B override one of the functions and force it to be private?
NO. Pointer/reference to A will always see my_func2 as public. You can still call this method using A* or A&. (what you ask is possible in Java).
==> if the inheritance type is private - can B force a specific function to be public?
At 1st place if the inheritance type is private/protected then you can NOT assign object of Derived class to Base class pointer/reference. e.g. you can not do following!!
A* p = new B; // error
==> What if A is pure abstract? does it make a difference?
NO difference (except you have to define methods in B)
==> Would protected make any difference in any combination?
NO difference (with respect to Base class)
I was going through posts made by others and found explanation related to errors encountered when inheritance being private/protected in Derived class somewhat confusing/incomplete.
Consider below code snippet,
class A
{
public:
virtual double my_func1(int i);
virtual double my_func2(int i);
}
class B : private A // Notice private inheritance
{
public:
virtual double my_func1(int i);
private:
virtual double my_func2(int i);
}
A* ptr = new B; // this is not legal because B has a private base
ptr->my_func1(); // my_func1() is not accessible
ptr->my_func2(); // my_func2() is also not accessible not because it is private but due
// base class A being inherited privately
So when we inherit class B from class A using private/protected specifiers then it means that nobody in outside world knows that class B has inherited from class A hence it's illegal to assign pointer/reference of type class B to pointer/reference of type class A. Hence, access of private/protected overridden virtual function in derived classes is only valid when inheritance in public.
What you override does not affect access. So you can create public override of privately inherited function exactly the same way you create private override of publicly inherited function.
The public override of the privately inherited function obviously has to call the real function and it should be inline, so the compiler will optimize it away.
First off I apologize if there is another post out there that answers this, all the similar posts I found dealt with diamond inheritance schemes or defined functions, which this does not.
In short, I'm wondering if it is possible to have one class inherit from two other classes where both child classes has a function with the same name and arguments but it is defined in one child class, and pure-virtual in another. Furthermore if I can do this, would invoking the function on the pure-virtual/abstract class end up calling the defined function on the other child class with minimal changes to the derived class?
Example:
class A
{
public:
virtual void Set(int X) = 0;
};
class B
{
public:
virtual void Set(int X);
};
class AB : public A, public B
{
//other methods not relevant to example go here
};
int main(int argc, char **argv)
{
int Y = 5;
A* ObjectA = new AB();
ObjectA->Set(Y);
return 0;
}
So far my attempts to compile this basic example have been met with errors that say:
'AB' : cannot instantiate abstract class
due to following members:
'void A::Set(int)' : is abstract
When doing my own research I couldn't find a clear answer, but based on other questions that dealt with related topics I found that using a "using B::Set" in class AB may help with this. But when I try adding it to the AB class definition, the error persists.
Is there any way I can make this work?
If you had 2 normal functions Set in A and B, then using B::Set would tell the compiler that if you have object of class AB and call method Set of that object, B::Set will be invoked, if AB::Set not defined explicitly.
Your situation is different. You have pure virtual function A::Set that leads A to be abstract class. As AB does not override A::Set, AB becomes abstract too, that is why you cannot instantiate it.
What you can do here
You can implement AB::set to call B::Set:
class AB : public A, public B
{
public:
void Set(int x) { return B::Set(x); }
};
Also I do not recommend same method names for base classes, as I do not recommend multiple inheritance, try use aggregation instead.
Have you tried implementing the method:
class AB : public A, public B
{
void Set(int X) {}
};
The reason it's not working is that A::Set() is pure virtual. I.e. it has no implementation. But you try to call it. You have to override it in the derived class in order to be able to instantiate the derived class.
The using doesn't work in your case because you have an A*, so there's no ambiguity for the compiler.
In case you had:
AB* ObjectA = new AB();
ObjectA->Set(Y);
you'd have to use using inside the declaration of AB to resolve the ambiguity.
Class AB derives from A, A has a pure virtual method making the class abstract, AB must implement any pure virtual methods declared in a base class in order to be instantiated.
I would try to avoid multiple inheritance it can cause many headaches and there are generally better ways to solve a problem, for instance in this example I don't understand the point in deriving from both A and B, if B shares and in fact implements the same interface as A then surely B should be derived from A.