C++ - Is possible to have subclass contain the containing class by value? - c++

class Containing{
class Subclass{
Containing cont;
};
};
Currently this says "error: field cont has incomplete type". Is this not possible at all with C++? Or when someone needs this does it mean they have wrong program design? Should Subclass be a derived / separate class instead?

This is the same problem as
class Containing;
class Subclass
{
Containing cont;
};
You can solve it in the same way as the non-nested problem, by defining the dependent class after the class it depends on.
class Containing
{
class Subclass;
};
class Containing::Subclass
{
Containing cont;
};

I think what you want could be a pointer:
class Containing;
class Containing{
class Subclass{
Containing* cont;
};
};
In Java, class instances are pointers by default. This means that this is just an address value which contains the address of the Containing object. So the cont is a separate instance which you refer to by the pointer. Your code doesn't work because the declaration of Containing isn't finished, thus Containing isn't known yet. It would need its own declaration to finish its own declaration.
What I did above the class is a forward declaration. This means I told the compiler that there is a class with the name Containing declared. Then you can use a pointer to Containing, because you don't have to know anything about the members or the size of Containing.
Be aware, that you by default have no pointer, you first need an instance of Subclass, maybe this is even what you want:
class Containing;
class Containing{
Containing* cont;
};

Related

Can a derived class be smaller than its parent class?

I'm asking this about C++ since I'm familiar with that but the question really explains itself: is there a language in which we can derive a class and make it occupy less space in memory than the original class?
This question is more of a gimmick than an actual problem I'm trying to solve, but I could imagine that some really high-performant code could benefit from this kind of memory optimization:
Suppose we have:
class Person {
std::string name;
unsigned int age;
}
class PersonNamedJared {
}
In theory, we don't need a field "name" in this subclass since it'll always be "Jared", which could allow for better memory efficiency.
Is the only way to make this happen by replacing the 'name' field in Person with a get_name() function that we simply override in PersonNamedJared to always return "Jared"? How would we still make the name variable in the base class?
I know this example is really bad practice, but it's the best I could come up with. I think there are legitimate reasons to implement this kind of pattern.
Can a derived class be smaller than its parent class?
No. A derived class always contains a base class sub object. An object can never be smaller than its sub objects, so a derived class can never be smaller than its base.
Is the only way to make this happen by replacing the 'name' field in Person with a get_name() function that we simply override in PersonNamedJared to always return "Jared"?
That would be one way to achieve it.
How would we still make the name variable in the base class?
You couldn't have a member variable in a base that you don't want to be in the derived class.
You could for example use multiple inheritance so that you do have a base with the variable in some derived classes. Something like this:
struct Person {
unsigned int age;
virtual std::string name() = 0;
...
struct Named {
std::string name;
};
struct NamedPerson : Person, private Named {
std::string name() override {
return name;
}
};
struct JaredPerson : Person {
std::string name() override {
return "Jared";
}
};
Here, there is a base with the variable, but Jared does not inherit that particular base.
No.
Inheriting from a class means that you include all its member variables, it's parent class[s] member variables, plus whatever your own class contains.
To put it another way, child classes are a superset of parent classes. (with the exception of an empty child class)
Even private members are still there taking up space, it's just a compiler error to try and access them.
Can a derived class be smaller than its parent class?
In C++, No!
Even if you try to replace a member of the base class with a smaller member in the derived class (by using the same name), the base class member is still there (it's just harder to access). This code will demonstrate that, with the derived class actually adding to the size of the base:
#include <iostream>
class A {
public:
double q[200];
};
class B : A {
public:
double q[100]; // Can we replace base array with a smaller one?
};
int main()
{
std::cout << sizeof(A) << std::endl; // -> 1600 = 200 * sizeof(double)
std::cout << sizeof(B) << std::endl; // -> 2400 ADDS 100 more doubles!
return 0;
}
The answer should be clear if you make use of polymorphism. That is, take advantage of the language features that let you view an object of a derived type as one of a base type. Assume Person is a public base of PersonNamedJared and consider the following code.
PersonNamedJared Jared;
Person * Pointer = &Jared;
std::cout << Pointer->name << " is " << Pointer->age << " years old.";
This is valid, but how could this code possibly work if PersonNamedJared lacked a name field?
As a rule of thumb, if you have a legitimate reason to want a derived class to be smaller than its base class, then there is probably something wrong with your class design.
With regards to could there be a language that has this feature, I think it is possible, but rather awkward. You could – in a hypothetical language – blur the line between data members and function members by allowing the identifier name to represent (virtual) data in the base class but a function in derived classes. So a derived class could provide a function called name, overriding the base class version. You could block explicit references to the base class version of name when dealing with an object of derived type. With enough requirements and prohibitions, the name field would inaccessible in certain derived class objects, hence it would not be needed by them. In that case, the name field could be omitted. (However, I am not aware of any language that permits this stringent setup.)
On the other hand, this setup feels like it runs counter to the principles of inheritance. Even if a language allowed this setup, I would prefer better class design.

virtual function with user-defined-type vector

I want to define an abstract base class with a vector of struct variables, and a virtual function to be implemented by derived classes:
class TestFather {
private:
struct myStruct
{
// struct definition
};
vector<myStruct> myStructVect;
public:
virtual vector<myStruct> get_myStructVect() = 0;
};
but when I write the derived class:
#include "TestFather.h"
class TestSon : public TestFather{
private:
struct myStruct
{
// struct definition
};
vector<myStruct> myStructVect;
public:
vector<myStruct> get_myStructVect();
};
I get this error:
invalid covariant return type for ‘virtual std::vector<ProvaSon::myStruct, std::allocator<ProvaSon::myStruct> > ProvaSon::get_myStructVect()’
Am I doing something wrong or maybe I'm trying to do something that is forbidden by the language?
The two myStruct types are totally unrelated. This means that you're trying to override TestFather::get_myStructVect() and have it return a completely different type. This is not allowed.
You don't have to redefine the struct in TestSon, and you also can't do this. The caller of fatherptr->get_myStructVect statically gets a vector<TestFather::myStruct> back, so the compiler forbids you to override the base class function like that, because the dynamically returned object would potentially be incompatible with vector<TestFather::myStruct> (who knows what you put into TestSon::myStruct and how vector differs in behavior from the base class vector?).
As for the allowed difference, C++ only allows the derived class return type to be a derived class of the base class return type, and only when the return types are pointers or references.
It's forbidden. Because you've redefined myStruct in your derived class, vector<myStruct> is a different type in the derived class than it is in the base class. They are two different myStructs.
You can only change the return type of that virtual function to something inherited from the return type declared in the base class. But vector<TestSon::myStruct> does not inherit from vector<TestFather::myStruct>
It says vector<myStruct> but since you changed myStruct in the child class it's actually two distinct types so each of the two functions thinks its returning a different type. This is only allowed for covariant types where the type is related to the actual type of the class containing the function.
Note that you probably shouldn't be returning a class attribute vector by value here anyway.
I can't tell what you really are intending to do, but the nested structures really shouldn't have the same name if they're two different things (and if they're the same, don't redefine it). My first gut reaction is that maybe the parent-child relationship isn't appropriate here. Have you considered other options? If you really need to return a different type in the child and the parent doesn't know about that, then you can't use a virtual interface to do this. You should just give the functions different names so you know what the return type should be.
With more details about your goals a better answer could be provided.
The duplicate private structure is a bit odd in your example. The below compiles fine, for instance:
class TestFather {
protected:
struct myStruct
{
// struct definition
};
vector<myStruct> myStructVect;
public:
virtual vector<myStruct> get_myStructVect() = 0;
};
class TestSon : public TestFather{
public:
vector<myStruct> get_myStructVect();
};
int main(int argc, char**argv)
{
TestSon testSon;
}
Note the replacement of private with protected, allowing derived classes access to the parent structure definition and myStructVect storage.

C++: Two classes needing each other

I'm making a game and I have a class called Man and a class called Block in their code they both need each other, but they're in seperate files. Is there a way to "predefine" a class? Like Objective-C's #class macro?
Yes.
class Man;
This will declare Man as an "incomplete type". You can declare pointers or references to it and a few other things, but you can't create an instance or access members of it. This isn't a complete description of what you can and can't do with an incomplete type, but it's the general idea.
It's called a circular dependency. In class Two.h
class One;
class Two {
public:
One* oneRef;
};
And in class One.h
class Two;
class One {
public:
Two* twoRef;
};
The "class One;" and "class Two;" directives allocate a class names "One" and "Two" respectively; but they don't define any other details beyond the name. Therefore you can create pointers the class, but you cannot include the whole class like so:
class One;
class Two : public One {
};
class Three {
public:
One one;
};
The reason the two examples above won't compile is because while the compiler knows there is a class One, it doesn't know what fields, methods, or virtual methods, class One might contain because only the name had been defined, not the actual class definition.

Is it possible to declare a class without implementing it? (C++)

I know the questions seems ambiguous, but I couldn't think of any other way to put it, but, Is it possible to do something like this:
#include<iostream>
class wsx;
class wsx
{
public:
wsx();
}
wsx::wsx()
{
std::cout<<"WSX";
}
?
Yes, that is possible. The following just declares wsx
class wsx;
That kind of declaration is called a forward declaration, because it's needed when two classes refer to each other:
class A;
class B { A * a; };
class A { B * b; };
One of them needs to be forward declared then.
In your example,
class wsx; // this is a class declaration
class wsx // this is a class definition
{
public:
wsx();
}
So yes, by using class wsx; it is possible to declare a class without defining it. A class declaration lets you declare pointers and references to that class, but not instances of the class. The compiler needs the class definition so it knows how much memory to allocate for an instance of the class.
This is the definition of the class
class wsx
{
public:
wsx();
}
This is the definition of the constructor
wsx::wsx()
{
std::cout<<"WSX";
}
THis is a forward declaration that says the class WILL be defined somewhere
class wsx;
Yes. But it is not possible to define a class without declaring it.
Because: Every definition is also a declaration.
You did define the class. It has no data members, but that's not necessary.
I'm not sure what you mean. The code you pasted looks correct.

In Inheritance: Can I override base class data members?

Let's say I have two classes like the following:
Class A
{
public:
..
private:
int length;
}
Class B: public Class A
{
public:
..
private:
float length;
}
What I would like to know is:
Is overriding of base class data members allowed?
If yes, is it a good practice?
If no, what is the best way to extend the type of the data members of a class?
There is a class that satisfies my needs and I want to reuse it. However for my program needs, its data members should be of another type.
I have some books, but all of them refer only to overriding of base class member methods.
You can use templatized members i.e., generic members instead of overriding the members.
You can also declare a VARIANT(COM) like union.
struct MyData
{
int vt; // To store the type
union
{
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
.
.
}
};
1) No you can't. You can create your own internal/hidden/private members, but you can't overide them.
2) If you could, not it wouldn't be good practice. Think about it ;)
3) You shouldn't, as you're changing the meaning of the member.
While declaring a data member of the same name in a derived class is legal C++, it will probably not do what you intend. In your example, none of the code in class A will be able to see the float length definition - it can only access the int length definition.
Only methods can have virtual behaviour in C++, not data members. If you would like to reuse an existing class with another data type, you will have to either reimplement the class with your desired data type, or reimplement it as a template so you can supply the desired data type at instantiation.
1) yes it is allowed, as in, you can do it
2) No! bad practice. If someone calls a method that use 'length' the variable being returned will be undefined.
3) Try a different design. Perhaps you want to have a similarly named function or use the baseclass as a "has-a" class instead of an "is-a" class.