Covariance and Hiding in C++ [closed] - c++

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Can someone please explain the reason behind input in each line ?
Class A {
bool f(A* a) { return true; }
}
class B : public A {
bool f(B* b) { return false; }
}
void f() {
A* a = new A();
A* ab = new B();
B* b = new B();
a->f(a); a->f(ab); a->f(b); // true, true, true
ab->f(a); ab->f(ab); ab->f(b); // true, true, true
b->f(a); b->f(ab); b->f(b); // error, error, false
}

B has two non-virtual methods with the same name: bool f(A*) and bool f(B*).
Normally, these would be overloads; but since one was inherited from a base class, it's hidden by the latter. It's still accessible, it just needs some special syntax to call it, for example:
B b;
B* param;
b.f(param); // calls B::f(B*)
b.B::f(param); // same
b.A::f(param); // calls the hidden A::f(A*)
So:
a->f(a); a->f(ab); a->f(b);
This one is easy: a is of type A*, so A::f(A*) will be called and argument of type B* will be converted to A*.
ab->f(a); ab->f(ab); ab->f(b);
Same thing happens, since ab is also of type A*.
b->f(a); b->f(ab);
These can't work since b is of type B* and b->f can only refer to B::f(B*) (A::f is hidden). You can't implicitly convert from A* to B*.
You can mention the hidden method explicitly, though:
b->A::f(a); b->A::f(ab);
And the last works, simply calls B::f(B*):
b->f(b);
Sample at ideone
Remarks:
It doesn't matter here whether the functions are virtual or not. They have different argument types, so one can't override another. One can only hide the other.
C++ allows covariant return types (you might want to have virtual A* foo() in A and virtual B* foo() in B if the args match). C++ doesn't allow covariant or contravariant argument types, though.

Related

How do I handle classes that reference each other? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
Here's the code:
class B
{
A a;
};
class A
{
B b;
};
int main()
{
return 0;
}
Here's the error:
1>c:\mine\visual studio 2010 projects\myproj\compiled equivalent.cpp(7):
error C2079: 'B::a' uses undefined class 'A'
You can't. Two classes cannot contain each other as members. Consider answering the question “What is the size of the type A?” Well A contains a B, so what is the size of B? Well B contains an A, so what is the size of A? Oh dear, we have an infinite loop. How would we possibly store this object in finite memory?
Perhaps a more appropriate structure would be to have one of the classes contain a pointer to the other type. The type that is pointed to can simply be forward declared before the pointer member is declared:
class A; // A is only declared here, so it is an incomplete type
class B
{
A* a; // Here it is okay for A to be an incomplete type
};
class A
{
B b;
};
Now the type B doesn't contain an A, it just contains a pointer to an A. There doesn't even have to be an A object for it to point to, so we've broken the infinite cycle.
Considering you ask for references between the classes, probably you come from Java, C# or similar background where one can only put references to objects inside other objects.
In C++ there is no such restriction: you are allowed to have one object's content completely nested inside another one. But for this to work you must provide the definition of the nested object beforehand. C++ needs this definition in order to compute the size and layout of the outer object. In order to escape from this nesting you need to place not the object itself but a pointer or reference to it inside the outer object.
That being said,
// C#
class A
{
int x;
B b;
}
class B
{
int y;
A a;
}
becomes
// C++
class B; // tell the compiler that B is a class name
class A
{
int x;
B *pb; // the forward declaration above allows you to declare pointer to B here
};
class B
{
int y;
A *pa;
};
if you decide to use the pointer syntax.
What this allows is to have things like:
// C++ again
class C
{
A a;
B b;
A *pa2;
};
which has memory layout in the form of:
C:
a.xa.pb
b.yb.pa
pa2
which is not possible in Java/C#.

Polymorphism , c++ [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Assume there are class A , and class B that inherits A. what is the correct way to use B objects?
I've seen in "cplusplus.com" that they are "using" B objects this way:
B b;
A* a=&b;
What's the difference between using a class "A" pointer and using b?
Thanks!
The advantage of using pointers to base classes comes when you have virtual functions.
Imagine the following
class A {
A(){}
virtual ~A(){} // note virtual destructor
virtual void func(){ cout << "A func" << endl; }
};
class B : public A {
B(){}
virtual ~B(){}
virtual void func(){ cout << "B func" << endl; }
};
class C : public A {
C(){}
virtual ~C(){}
virtual void func(){ cout << "C func" << endl; }
}
now if we have a pointer to base class we can call func() on it and the correct function is called depending on whether the pointer actually points at an A, a B or a C. Example:
A* p1 = new A;
A* p2 = new B;
A* p3 = new C;
p1->func();
p2->func();
p3->func();
will output the following
A func
B func
C func
Now you may say why not use three different pointers to A, B and C types separately but what if you wanted an array of pointers? Then they would all need to be the same type, namely A*. This type of polymorphism is useful for grouping things which are similar in function or spirit but different in implementation.
They only did that to show that you can, and that polymorphism is invoked when you do.
If you just want to use your B b, just use it; no A* required.
As an aside, learning C++ from internet tutorials is rather akin to learning how to cook by analysing some chewing gum you found in the street. Prefer a proper, peer-reviewed book.

C++ method calls from the same class [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
In C++, I want to be able to call a method in the same class without creating an object of the whole class. The class is huge and I do not want to create a huge memory location for an object. I am used to programming in C#.
In C# I could do this
class test()
{
private void A()
{
B();
}
private void B()
{
doSomething;
}
}
in C++ I am under the impression I have to do.
class test()
{
public:
static void A();
void B();
};
void test::A()
{
test t;
t.B();
}
void test::B()
{
doSomething;
}
}
I do not want to make B() static nor do I want to create and object of test because in reality my class is a lot larger than this, and creating a object of the class would use memory that I do not want to.
Is there a way I can accomplish what I could in C# in C++?
No. If B needs an object, you have to give it an object. If B doesn't need an object, declare it static. C# is no different -- in your example, A is not static so the object already exists.
static void A();
void B();
You cannot use static function to call non-static one at all.
Solution:
Mark B as static too (if it doesn't depend on current object) and thus you don't have to creat a new object. Else I think A should be non-static.

C++ polymorphism: going from base class to derived class [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
class A{};
class B : A{};
void func(A* p)
{
B* p2 = p; // Error
}
Your code has several oddities.
You use private inheritance. In private inheritance you will not be able to convert to a derived class ever when you are not inside the class scope itself.
Even if you would inherit publicly, you will need at least one virtual function (and that should be the destructor) in the base class to use dynamic_cast.
Chances are you are doing something wrong when you need a lot of down-casts. You should probably rethink your design or usage of the provided API.
Typically, things would look like this:
class A {
public:
virtual ~A() {}
};
class Derived : public A {
};
void func(A* a) {
if(Derived* d = dynamic_cast<Derived*>(a)) {
// yeah, a is of type derived
} else {
// a is not of type Derived
}
}
is-a relationship is implemented by public inheritance. as you are inheriting it privately this is association relationship which is not is-a. so B is not an A. So you cannot store A in B or A cannot become an B
and dynamic_cast will not work as source type is not polymorphic
neither would static_cast work as ‘A’ is an inaccessible base of ‘B’
To make an is-a relationship you need to do class B: public A{}
For classes private inheritance is used by default.

Invoking method in C++ [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
A question about C++ programming.
Can you do in C++ something like this:
Lecture le;
Carriage ca = le;
No casting, just writing like that. The problem is, when I am trying to invoke a method which belongs to Lecture class the methods is underlined in red.
ca.runIt();
I am not quite sure if I understood the specification of my task, but there is given this snippet of code. Best regards
Can you do in C++ something like this:
Yes.
struct Lecture {
};
struct Carriage {
Carriage(const Lecture&) {
}
void runIt() {
}
};
int main() {
Lecture le;
Carriage ca = le;
ca.runIt();
}
The problem is, when I am trying to invoke a method which belongs to Lecture class the methods is underlined in red.
Of course. ca isn't a Lecture. ca is a Carriage. You can only invoke Carriage methods on ca.
Let's break it down, from the general case to the most specific.
If you have some arbitrary class A and some other arbitrary class B, the statement:
A a;
B b = a;
is generally not going to work. It will certainly not work by itself; you have to put effort into making it work.
So now, let's get specific. If B is a class derived from A, then it will also not work. If A is derived from B, it will still not work.
Why? Because A a defines an object, not a reference. It creates a value. B b = a; is an attempt to store the value a into a new value b. You cannot do that.
If A is derived from B (B is the base class), you can do this:
A a;
B &b = a;
That's legal C++, and it's meaningful too. b now refers to part of a. Specifically, the part of a that is the base class.
Note that the reverse does not work. If A were the base class, C++ would raise an error.
Now, there is one way to make the general statement work.
A a;
B b = a;
If you want this to be reasonable for a specific class B, then B must be defined as follows:
class B ... //Whatever base classes you want.
{
public:
B(const A &a);
};
The constructor that takes a const A & is a conversion constructor. It's job is to create a B object using data from an a object. Because this conversion constructor was declared without the explicit keyword, then it can be used for implicit conversions like B b = a; If it were declared with the explicit keyword, you would have to explicitly convert it: B b = B(a);.
Having a conversion constructor on a class means that any instance of A can be converted into a B. So you can pass A to a function that takes a B (either by value or by const&. Not by reference) without having to do an explicit conversion.
Note that conversion constructing an object does not allow you to call functions from A on the object B. You can only call functions on B which B defines or are defined by one of B's base classes.