Overriding virtual method inside another class to access its member in c++ - c++

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().

Related

Member function of (public) derived class is inaccessible from main

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.

Does the code get copied to derived class?

Whenever I derive a new class from base class say:
#include <iostream>
class A {
protected:
int f;
public:
void get() {
std::cout << "The address is: "
<< &f << std::endl;
}
};
class B : public A {
// ....
};
int main() {
A a;
a.get();
B b;
b.get();
return 0;
}
The address is: 0xbfb0d5b8
The address is: 0xbfb0d5bc
Does this means that all the code from class A will be copied to class B? Since I have nothing in class B i.e. no data members or functions So, when I create an instance of class B, then I find that it has its own variable at different address and it also has a member function. How can it have its own of copy members if it they aren't copied?
Is that what do we mean by code reuse in inheritance?
Edit:
Updated my code to reflect what I meant by copying of variables.
Code is never copied during inheritance. But when the child object (class B) is created or instantiated at run time, it inherits the functionality and attributes of the parent class/object (class A).
the code from class A does NOT copied to class B in the sense that there is only one place the code is written.
however, and here cones the Reusable part, when using class b u can call the method and use the members, with respect to private, public, etd and thus does not have to write the same code for two class that do the same thing
for example if i have a circle and a square, and they both have a member called color that i want a method that change it, i do not need to write the method and the member twice, but have them inherit class Shape that will implement it once and then they both will be able to use that method, thus reusing one method in two places
I'm not sure "copied" is the right word (the compiler will only compile the code in class A once). As you have used public inheritance, class B actually is a special type of class A. As such, class B does have access to every (non-private) member of class A, so the code is re-used.
In addition, from the conversation in the comments:
No. Nothing is "copied", each instance of A and B has their own value for their own variables, except for any static data members. For static data members, again there is no copying going on; there is simply only one variable and that is shared by all instantiations of A and B.
In your example, you are comparing two different instances of two different classes. different instances means different base addresses to store instances data.
Perhaps a better test of whether a field of a class is copied over in derived classes is the following:
#include <iostream>
class A {
protected:
int f;
public:
void get() {
std::cout << "The address is: " << &f << std::endl;
}
};
class B : public A {
// ....
};
int main() {
B b;
b.get();
A *a = &b;
a->get();
return 0;
}
And the output is:
The address is: 0x7fff41d523f0
The address is: 0x7fff41d523f0
With that program, we can see that even though we have an instance of class B, its inherited content is physically the same as the one in the original class A. Note that it is also possible to redefine a class member in a derived class, but the original member will still be available if we coerce an instance of the derived class to the parent class (as I did in my example).
ยง1.8(2) of the C++ language standard defines what is meant by a subobject:
Objects can contain other objects, called subobjects. A subobject can be a member subobject (9.2), a base class subobject (Clause 10), or an array element. An object that is not a subobject of any other object is called a complete object.
These are examples of member subobjects and array elements, which you should be familiar with:
int a[5];
a[2]; // the third array element subobject of the complete object a
struct S { int x; }
S s;
s.x; // a member subobject of the complete object s
That leaves the remaining kind of subobject, the one which you are interested in: base class subobjects.
struct B { int x; }
struct D : public B { int y; }
D d;
d.y; // a member subobject of the complete object d
d.x; // a member subobject of a base class subobject of the complete object d
B &b = d; // a reference to a base class subobject of the complete object d
Every instance of a derived class contains an instance of its base class, as a base class subobject.
I also have some doubts regarding relation between inheritance and code re-use. This is my take on this.
Inheritance is a mechanism used to categorize and facilitate polymorphism. Using inheritance we can build a hierarchy of concepts separated in categories at different levels of abstraction. By doing this, we can efficiently use another OOP concept, polymorphism, which allows the same control code to manage all objects in a category even if they are different in their implementation.
I don't think that we use inheritance for code re-use purpose.

C++ nested classes, access fathers variables [duplicate]

This question already has answers here:
Can inner classes access private variables?
(5 answers)
Closed 6 years ago.
The title already says a lot,
but basically what i want to do is the following(Example):
I have a class called A, and another class inside a called B, like so:
class A
{
int a;
class B
{
void test()
{
a = 20;
}
};
};
As you can see my goal is for class B to have access to class A, as it is a nested class. Not this wont work, because B doesn't have access to A, but how can it get access?
Thank You
Despite that you declared class B inside of A, classes A and B are still completely independent. The only difference is that now to refer to B, one must do A::B.
For B to access A's stuff, you should use composition or inheritance. For composition, give B a reference to an object of A, like so:
class B {
public:
B(const A& aObj) : aRef(aObj) {
cout << aRef.a << endl;
}
private:
const A& aRef;
};
For inheritance, something like this:
class B: public A { // or private, depending on your desires
B() {
cout << a << endl;
}
}
The inner class is not related to the outer class in C++ as it is in Java. For an instance of A::B to access a member of an A object, it needs to have an instance of A somewhere, just as if B were not a nested class. Instances of A::B do not have any implicit instance of A; you can have many instances of A::B without any instances of A existing at all.
Pass an instance of A to test, and then use it to access the a member:
void test(A& a_instance)
{
a_instance.a = 20;
}
Classes are types, types don't have data. Instances have data, but an instance of A does not (in your example) contain an instance of B, and the instances of B don't have any knowledge of any instance of A.
Choices
have B be a child of A instead of contained by A
have B's constructor take a ref to the A instance which created it (preferred)
Now, if the variable a is private this still won't help. You will either need an accessor a or a friend relation.
C++ nested classes are not like java nested classes, they do not belong to an instance of A but are static. So a doesn't exist at that point

C++ Accessing a private structure from another class

I have a class as shown below:
class B;
class A
{
public:
A();
~A();
void createStuff(.......); //??
private:
B *b;
};
The object B contains another of class 'C' which has about 20 class member variables.
I want the user of class A to be able to call the function createStuff(...) with a set of arguments so that I can construct the object C. What is the best way of doing this?
The mechanism for classes to grant access to their private members is called friendship.
With what you have posted it looks like something like this may work:
class B
class A:
{
public:
A();
~A();
void ceateStuff(.......); //??
private:
B *b
}
void A::createStuff(argument1, argument2...)
{
C = new C(argument1, argument2...) //You now have an instance of C with the arguments pass in to createStuff();
}
The variable of type C belongs to class B; it mediates the access to the data in C. Class B has constructors; you will use those to set the variable of class B in order, and it is B's job to ensure that the C is correctly managed.
If you need more control over C, then you have a design problem. Either your class A needs its own variable of class C to control, or class B does not provide the tools you need and needs fixing, or you are misguided in thinking you need access to, and therefore direct control over, the contents of the variable of class C.
The Law of Demeter is a guide in such scenarios; you seem to be wanting to contravene it.
In any case you should look at B class, how it implement initialization of C object, can it be controlled (If can't - you should extend interface of class B and add this functionality)?
If C definition is accesible for A maybe you can use constructor of B in such way:
void A::createStuff( const C& c)
{
b = new B(c);
}

Virtual functions and polymorphism

Suppose I have this:
class A
{
public:
virtual int hello(A a);
};
class B : public A
{
public:
int hello(B b){ bla bla };
};
So, A it's an abstract class.
1)In the class B, I'm defining a method that its suppose overrides the A class. But the parameter it's slightly different. I'm not sure about this, is this correct? Maybe because of polymorphism, this is ok but its rather confusing.
2) If I do: A a = new B;, and then a.hello(lol); if "lol" it's not of type B, then it would give compile error?, and if it's of type A from another class C (class C : public A), what would happend?
I'm confused about the overriding and virtual thing.. all examples I found work with methods without parameters.
Any answer, link, or whatever it's appreciated.
thanks
pd: sorry for my english
Your class B doesn't override the member function in A, it overloads it. Or tries to anyway, see the bit about hiding later.
Overriding is when a derived class defines its own version of a virtual member function from a base class. Overloading is when you define different functions with the same name.
When a virtual call is made on a pointer or reference that has the type of the base class, it will only "consider" overrides in the derived class, not overloads. This is essential - for an instance of B to be treated by callers as though it does everything an A can do (which is the point of dynamic polymorphism and virtual functions), its hello function needs to be able to take any object of type A. A hello function which only takes objects of type B, rather than any A, is more restrictive. It can't play the role of A's hello function, so it's not an override.
If you experiment a bit with calling hello on A and B, passing objects of type A or B, you should be able to see the difference. A has a function taking an A (which you haven't defined, so if you call it then your program will fail to link, but you can fix that). B has a function taking a B. They happen to have the same name, and of course since B derives from A, you can pass a B to the function taking an A. But B's function doesn't act as an override in virtual calls.
It is possible to call A's function on a B object, but only via a reference or pointer to A. A feature of C++ is that the definition of hello in B hides the definition in A. If overloading is what you want, it's possible to un-hide the base class function by adding using A::hello; to class B. If overriding is what you want, you have to define a function taking the same parameters. For example:
#include <iostream>
class A
{
public:
virtual int hello(A a) {std::cout << "A\n"; }
virtual int foo(int i) { std::cout << "A::Foo " << i << "\n"; }
};
class B : public A
{
public:
using A::hello;
// here's an overload
int hello(B b){ std::cout << "B\n"; };
// here's an override:
virtual int foo(int i) { std::cout << "B::Foo " << i << "\n"; }
};
int main() {
A a;
B b;
a.hello(a); // calls the function exactly as defined in A
a.hello(b); // B "is an" A, so this is allowed and slices the parameter
b.hello(a); // OK, but only because of `using`
b.hello(b); // calls the function exactly as defined in B
A &ab = b; // a reference to a B object, but as an A
ab.hello(a); // calls the function in A
ab.hello(b); // *also* calls the function in A, proving B has not overridden it
a.foo(1); // calls the function in A
b.foo(2); // calls the function in B
ab.foo(3); // calls the function in B, because it is overridden
}
Output:
A
A
A
B
A
A
A::Foo 1
B::Foo 2
B::Foo 3
If you take away the using A::hello; line from B, then the call b.hello(a); fails to compile:
error: no matching function for call to `B::hello(A&)'
note: candidates are: int B::hello(B)
A bunch of good answers telling you WHAT happens, I thought I'd jump in with WHY.
There's this thing called the Liskov Substitution Principle, which says that the function in the subclass has to work under the same preconditions and postconditions as the base class. In this case, the function has to be able to operate on any object of type A. Note that because of the inheritance relationships, every B is-a A, but not every A is-a B. So to replace the base method, the new function in the derived class can weaken the preconditions or strengthed the postconditions, but not strengthen preconditions or weaken postconditions.
Your attempt to override strengthens the precondition, it accepts Bs, not all As.
Note that covariance IS allowed on return types. If your base class returned A, then it guarantees that the return value is-a A. The base class could then return a B, because every B is-a A.
But for input parameters, only contravariance meets the theoretical requirements of the LSP, and in/out parameters are invariants. In C++ in particular, all parameter types are invariant for the purposes of overloading.
First, A is not an abstract class in your code. It must have at least one pure virtual function to be abstract.
different parameters means completely different method, even though the name is the same. Think of it as a different name. That's why it's called "signature". If A would be an abstract class, this code would not compile at all.
A::hello() will be called. No problem with that, and parameter must be type A, as if there was no inheritance.
When you override a method, it redefines what the method will do. You can only override virtual members that are already defined (with their set of parameters). If the type is of A, the method on A will be called. If the type is of B, the method on B will be called even if the variable is typed A but contains an instance of type B.
You can't change the parameter definitions for an overridden method, or else it would cease to be an override.
What you are doing there is overloading not overriding, i.e. it's as if class B is:
class B
{
public:
int hello(A a) {...}
int hello(B b) {...}
};
You have two functions of the same name, but with different signatures, which makes them different functions (just like the standard library has different functions for abs(float) and abs(double) etc.)
If you want to override, then you need to have the same signature, i.e. class B's hello needs to take a parameter of type A. That way, when you call hello on an object of class B, it will use class B's hello rather than class A's.
If you actually want class B's hello to only accept objects of type B then what you have is fine, although you probably want to make class A's hello non-virtual as you are not really wanting to override it -- you are defining a new function with new parameters and new behaviour.
Thansk for the answers, but I have to clarify some things to get my final answer.
Suppose I have the A class exactly how I defined it in the original question. And I add another method:
class A {
...
int yeah();
}
Then I define class B as the following:
class B : public A {
int hello(A a);
};
And another class C analogous to B.
What I know because I'm the programmer, it's that the hello methods of B and C are gonna have obviously A type objects as parameters, but instances of the same class.
In example:
B b;
b.hello(some_other_b_instance);
or
C c;
c.hello(some_other_c_instance);
The problem is that in each hello function of the classes B and C, I want to do particular things with atributes of the particular class B or C. And because of the parameter is of type A, I cannot use them.
What I would need it's a kind of inverse polymorphysm, but its wrong because by definition I can send a C instance to B hello class, but I know it's not gonna happend.
I hope you get the idea of the code... A clase is abstract, and the real work makes sense in the particular clases B and C, each one do the work in their particular way to make the yeah function work. But B and C need to access their members to do the hello work correctly.