Details and benefits of using a struct in a class definition - c++

Consider the following code:
class myclass
{
public:
//some public stuff
private:
struct classitem
{
int x;
classitem *next;
};
}
What I do not understand is this;
Is classitem just a definition, or will it already be a member of an object of this class? In other words, will it be filling any memory when we create an object of this class? If it is just a definition, how would we use it in future?
And what would be the benefits of using this struct in class definition instead of defining it outside of the class?

It will be just a definition.
If you want an object, use:
struct T { ... } instance;
The inner struct will be scoped in the outer struct definition - as to why it's useful, you can make the type (class) definition private for instance, if you don't want that type to be used outside of your class.
class NHeadedBeast {
struct Head {
Head() : numHeads{2}, eyesPerHead{4} { }
int numHeads;
int eyesPerHead;
} head;
public:
int getEyeCount() const {
return head.eyesPerHead * head.numHeads;
}
};
Notice how specific the Head class is - and also, it's called Head, which has a decent chance of colliding with some other type name. In other words, noone would ever want to use that Head type without my NHeadedBeast class, so might as well make the type inaccessible and isolate it in the NHeadedBeast scope.

Related

Is it relevant to use nested struct?

I'm trying to define a class that has private struct and public struct.
Private struct is the struct that will only be used by the class (e.g. SNode), and I don't want it to be visible outside the class because I don't want it to be mistakenly used (e.g. new Node()). Thus, I reached to the idea to set it basically hidden.
Public struct is the struct that will be used outside (e.g. SKeyValuePair), and it will have a pointer to a SNode.
Code Example is below.
[Class Definition]
template <typename T>
class A
{
private:
struct SNode
{
SNode* pParentNode;
SNode* pLeftChildNode;
SNode* pRightChildNode;
...
};
public:
A<T>()
{
}
virtual ~A()
{
}
struct SPair
{
private:
public:
SNode* pNode;
unsigned long long ullKey;
T value;
...
};
const SPair GetMinKeyPair()
{
return SPair(...);
}
const SPair GetNextMinKeyPair()
{
...
return SPair(...);
}
};
[Usage]
A a;
...
for (A::SPair pair = a.GetMinKeyPair(); pair.pNode != nullptr; pair = a.GetNextMinKeyPair())
{
...
}
Q1. I wonder if this kind of nested struct (which public struct containing private struct pointer) should be avoided for some reason I currently don't know.
Q2. If there are reasons, I wonder what they are.
In general, this is not a bad way to do business.
It keeps the name SNode<T> private when it doesn't need to be public. (Though, as aschepler noted in comments, be aware that the type itself can still be used in full via auto; accessibility affects only names.)
So this is quite a neat way to organise things, and I do personally make use of nested types.
However, since A is a class template, you're going to have a copy of SNode for each T that you use. That's just how templates work. This means more code and a larger executable. For that reason, you might consider the more conventional approach of just putting the utility types in a namespace instead. Does it really matter whether people try to use them outside of A<T>?

How should a member class access to the member functions?

This is a question to find out the better programming practice:
In C++, say I have two classes one of which is a member class of the other, e.g.,
class SomeClass {
public:
MemberClass member_class;
void set_num(double num_) { num_ = num; }
double num() {return num_; }
private:
double num_;
}
I want the member class to have access to the member functions of the outer class, e.g.,
class MemberClass {
public:
PrintSquare() {
cout << num() * num() << endl;
}
}
I am trying to achieve this in order to reduce the number of function arguments I am passing all around the program.
The most common (and IMHO proper) way to solve this problem is, introducing an interface (or even more interfaces focusing on particular sets of method features) for the containing class, and pass that one to the 'inner' class member on construction:
struct Interface {
virtual void set_num(double num_) = 0;
virtual double num() const = 0;
virtual ~Interface() {}
};
class MemberClass {
public:
MemberClass(Interface& interface) : interface_(interface) {}
PrintSquare() {
cout << interface_.num() * interface_.num() << endl;
}
private:
Interface& interface_;
};
class SomeClass : public Interface {
public:
MemberClass member_class;
SomeClass() : member_class(*this), num_() {}
virtual void set_num(double num_) { num_ = num; }
virtual double num() const { return num_; }
virtual SomeClass() {}
private:
double num_;
};
NOTE:
Calling methods of the interface though will fail (with a runtime exception), when called from the MemberClass constructor definition.
Although the answer by Kerrek is very interesting, he himself already states this normally isn't the way to go. Common practice would be to make the inner class nested in the outer one, if possible. If the inner one needs access to the outer one in such a way that a nested connection seems natural, this would be the way to go. Construction of an Inner object would then need a reference to the object it is a member from, in order to be able to call functions on its parent:
class Outer
{
class Inner
{
Outer &parent; // consider constness
public:
Inner(Outer &_parent); //initializes the parent-reference
void innerFunction(); // can call members of parent
};
Inner inner;
public:
Outer(): inner(*this) { ... } // initialize inner
};
Depending on the standard you're using, the innerFunction now has access to all public members of Outer (C++03), or even all private members as well (C++11). See also this topic:
C++ nested classes - inner/outer relationship
EDIT: Did a quick test, and my compiler (gcc 4.7.2) also allows access to private members with older standards. Maybe someone could comment on this...
If your classes are all standard-layout, then you can take advantage of some layout guarantees that C++ makes, namely that a on object of standard layout type may be treated as if it were its own first member. For instance:
struct Foo
{
int a;
void barely_legal();
};
struct Bar
{
Foo x;
int y;
};
#include <type_traits>
void Foo::barely_legal()
{
static_assert(std::is_standard_layout<Foo>::value, "Foo");
static_assert(std::is_standard_layout<Bar>::value, "Bar");
Bar * p = reinterpret_cast<Bar *>(this);
++p->y;
}
This is unusual at best and cruel at worst, so please don't write code like this unless you have a really good reason to do so. (I know people who do have reason to do this, but I don't turn my back towards them.)

Multiple public/private keyword in class definition

I have seen multiple public and private keywords in a class definition, like the example below:
class myClass
{
public:
void func1(){}
public:
void func2(){}
private:
int x;
int y;
private:
int z;
int baz;
};
What is the practical use of this (if any)? Is there any situation in which this could be useful?
Is there any situation in which this could be useful?
I can think of a situation where it would be very problematic otherwise:
class myClass
{
public:
void func1(){}
public:
void func2(){}
COORDINATES; // <-- Note the macro here!
private:
int z;
int baz;
};
which, after the expansion of the COORDINATES macro, becomes:
class myClass
{
public:
void func1(){}
public:
void func2(){}
private:
int x;
int y;
private:
int z;
int baz;
};
If multiple private / public keywords weren't allowed, it would be very painful to do it. Although using macros isn't good practice; neither is introducing access modifiers silently for all the members appearing after the macro. Nevertheless, it could be useful for RAD tools generating C++ source code.
I can only guess why you see that in human written classes. My guess is that it is poor coding; the writer probably wanted to express that a chunk of data belongs together and / or wanted to be able to move up and down those chunks within the class definition, together with the corresponding access modifier (private/protected/public).
I'll go one step farther from my comment for this answer, with a snippet of code.
class myClass {
// initializers etc
public:
myClass();
~myClass();
// signal processing
public:
void modifyClass();
private:
float signalValue;
// other class responsibilities
public:
void doWork();
private:
void workHelper();
};
and so on. I wouldn't say this is a solid DESIGN for the class, but it's a good way to show the different capabilities of a class.
Another use is when you want to have a specific destruction order. Lets consider two cases:
Bad case
// Auxiliary class
Class StorageCleaner {
public:
StorageCleaner(ExternalStorage* storage) : storage_(storage);
~StorageCleaner() { storage_->DeleteEverything(); }
private:
ExternalStorage* const storage_; // Not owned
}
// Class with bad declaration order
Class ExternalStorageWrapper {
public:
ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
pointer_to_storage_.reset(storage);
}
const StorageCleaner cleaner_;
private:
std::unique_ptr<ExternalStorage> pointer_to_storage_;
// Other data which should be private
int other_int;
string other_string;
....
};
What happens when existing ExternalStorageWrapper object goes out of scope?
The ExternalStorageWrapper destructor will first
destroy other data
Then it will destroy external storage pointed by pointer_to_external_storage_ (because fields are destroyed in reversed declaration order).
Then it will attempt to destroy cleaner_
But cleaner inside its own destructor attempts to manipulate external storage, which has already been destroyed!
Good case
// Class StorageCleaner same as before
...
// Class with better declaration order
Class ExternalStorageWrapper {
private:
std::unique_ptr<ExternalStorage> pointer_to_storage_;
public:
ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
pointer_to_storage_.reset(storage);
}
const StorageCleaner cleaner_;
private:
// Other data which should be private
int other_int;
string other_string;
....
};
What happens in this case when existing ExternalStorageWrapper object goes out of scope?
The ExternalStorageWrapper destructor will first destroy other data.
Then it will attempt to destroy cleaner_. Cleaner will DeleteEverything() from storage using storage_ pointer to still existing storage.
Finally, storage gets destroyed through pointer_to_storage_.
I actually had to debug such problem in a company, so although rare, this peculiar case is possible to occur.
One use case I encounter is for the clarity. As shown in the example below, class1 inherits base class which contains a pure virtual function that class1 needs to implement. To indicate that method1 in class1 is coming from some other class class1 inherits from (e.g. base) instead of class1's own function, we use another public to make this point clear:
class base {
public:
virtual void method1() = 0;
}
class class1: base {
public:
myOwnMethod1();
myOwnMethod2();
public: /* base interface */
method1();
Just finished reading those examples. Hopefully this one could contribute on how useful multiple keyword definition is.
We don't quite need to assume much since this is my current problem as of now but consume the following:
class IOHandler {
public:
enum COLOR_DEFINITIONS : unsigned char
{
BLACK,
DARK_ER_BLUE,
DARK_GREEN,
DARK_SKY_BLUE,
DARK_RED,
DARK_PINK,
DARK_YELLOW,
DARK_WHITE,
DARK_GREY,
DARK_BLUE,
BRIGHT_GREEN,
BRIGHT_SKY_BLUE,
BRIGHT_RED,
BRIGHT_PINK,
BRIGHT_YELLOW,
BRIGHT_WHITE
};
template <typename dtEX>
void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
// ! ^^^^^^^^^^^^^^ Doesn't detect the struct being referenced at which is at below.
private:
typedef struct colorProps // This is the struct that the public function where trying to get referenced at but failed to do so.
{
unsigned char C_BG = 0,
C_FG = 0;
} _COLOR_OUTPUT;
};
The error code.
identifier "_COLOR_OUTPUT" is undefined.
At this point, my intelliSense keep complaining that _COLOR_OUTPUT is undefined within public class scope.
The most probable solution is to put the struct inside public scope instead of private scope.
But I don't want to.
The reason this happens was due to the compiler reads the file from top to bottom. Anything that is declared
that requires reference should be on top and that should resolve the issue. Since I don't want to make things messed up by putting all private class functions and variables
on top. I should just declare another specifier on the top so that any public function requiring some reference might see it ahead.
So the solution is the following: (Is to move all referrable variables and struct on top of the class so that any private and public function argument reference is being recognized.)
class IOHandler {
// Private Class Scope for Variables and Structure
private:
typedef struct colorProps // This is the struct we move at the top for recognizing references.
{
unsigned char C_BG = 0,
C_FG = 0;
} _COLOR_OUTPUT;
public:
enum COLOR_DEFINITIONS : unsigned char
{
BLACK,
DARK_ER_BLUE,
DARK_GREEN,
DARK_SKY_BLUE,
DARK_RED,
DARK_PINK,
DARK_YELLOW,
DARK_WHITE,
DARK_GREY,
DARK_BLUE,
BRIGHT_GREEN,
BRIGHT_SKY_BLUE,
BRIGHT_RED,
BRIGHT_PINK,
BRIGHT_YELLOW,
BRIGHT_WHITE
};
template <typename dtEX>
void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
// ! ^^^^^^^^^^^^^^ Now recognizable reference.
private:
... // Any other functions, excerpt.
};

C++ Access private member of nested class

The title might be a bit misleading. I have the following problem: I have a tree consisting of leaves and internal nodes. The user should be able to store any information in the leaves and the tree has some methods which get a set of user-defined values and need to access the corresponding leaves in constant time (not amortized).
I came up with the following idea but it does not work because unfortunately I cannot access private members of a nested class: The user creates the tree and also for each leaf an instance of UserElement which contains the user_defined value for the corresponding leaf. Once a method like doSomethingWithTheTree(list>) is called and the tree is built, the tree creates the corresponding leaves and saves it in the private field leaf. Whenever the user wants to call a method with some of the leaves corresponding to its user_defined values, he/she just has to call the method by giving the corresponding UserElements and the tree can retrieve the corresponding leaves in constant time.
class Tree {
public:
template <typename T>
class UserElement {
private:
T user_value;
tree_node* leaf; // this has to be private for
// everyone outside the class `Tree`
public:
T getInf() {
return user_value;
}
void setInf(T i) {
user_value = i;
}
};
void doSomethingWithTheTree(list<UserElement<T>> elements) {
...
// I want to be able to access elem.leaf for all elements
}
}
Technically, that's a nested class (declared within another class), not a subclass (which inherits from its superclass).
You can allow the Tree class to access its privates by making it a friend:
class UserElement {
friend class Tree;
// ...
};
or, for better encapsulation, you could restrict access only to the member function(s) that need it, although it gets a bit messy due to the need to declare things in the right order:
class Tree {
public:
// Declare this so we can declare the function
template <typename T> class UserElement;
// Declare this before defining `UserElement` so we can use it
// in the friend declaration
template <typename T>
void doSomethingWithTheTree(list<UserElement<T>> elements) {
elements.front().leaf;
}
template <typename T>
class UserElement {
// Finally, we can declare it a friend.
friend void Tree::doSomethingWithTheTree<T>(list<UserElement<T>>);
// ...
};
};
You may do
class Outer {
private: // maybe protected:
class Inner {
public:
....
};
};
or
class Outer {
public:
class Inner {
friend class Outer;
private:
....
};
};
You can declare class Tree a friend to UserElement<>, which would allow Tree to access all members of UserElement<>.

Class within class - incomplete type is not allowed

class Publicatie{
public:
class Carte : public Publicatie{
private:
char* autor;
};
class Revista : public Publicatie{
private:
char* frecventa_aparitie;
int numar;
};
private:
int cota;
char* titlu;
char* editura;
int anul_aparitiei;
int tiraj;
Carte* c;
Revista* r;
public:
//some methods...
}
This is the code, i'm declaring the class Carte and Revista inside the class Publicatie and i need to have private members Carte and Publicatie. I really don't know how to do the design with inheritance with these classes. I get the error in the title for the inheritance :public Publicatie and i thought that it will work because the class is already created ( even though it's private members were not created yet).
your design is wrong. you're trying to define a class, and in it's definition you're trying to use from itself; it is a logical paradox.
from what i can understand from your code, you're trying to create a class named Publicatie that represents a publication (or a post) and it has two other variants, named Carte and Revista. if this is the case, why the Publicatie needs to have two private members of type Carte and Revista? maybe you can remove these two members from it.
or maybe you can move some of their shared members (such as titlu, tiraj and...) to another class that is abstract, and then define Publicatie, Carte and Revista such that all of them inherit from the same parent class.
hope these work.
You can only inherit from a class that is a complete type. However, you don't need to have the nested class definition inside your ambient class definition. Instead, you can do it like so:
struct Foo
{
struct Bar;
Bar * p;
int get();
};
struct Foo::Bar : Foo
{
int zip() { return 4; }
};
int Foo::get() { return p->zip(); }