This question already has answers here:
Why is a class allowed to have a static member of itself, but not a non-static member?
(2 answers)
Closed 8 years ago.
How can I make an instance of a class inside its definition?
class Test{
Test _test;
};
This throws
error: field _test has incomplete type
Using a pointer works but I would like to avoid using a pointer if possible.
Just imagine you could do something like that: this would be a recursive definition. An object of type Test contains an object of type Test, which contains an object of type Test, and so on without a termination until you or your compiler go crazy.
I don't really think you would want anything like that, even if it compiled. Using pointers, on the other hand, is OK for two reasons:
A pointer could by null, thus breaking the otherwise infinitely recursive chain of Test objects (which would take infinite space at run-time);
A pointer has fixed size, so the compiler doesn't need to compute the size of Test in order to compute the size of Test itself (leading to infinite recursion at compile-time).
Using a pointer works but I would like to avoid using a pointer if possible.
If you are worried about manual memory management, just use a smart pointer:
#include <memory>
class Test
{
std::unique_ptr<Test> _test;
};
Answer this question: how big would your class be?
The only two solutions I can think of is either by using a pointer:
class Test
{
public:
Test * data;
};
This solution is common in advanced structures, such as lists or trees.
Another way is to declare the internal field as static:
class Test
{
public:
Test(int i);
static Test data;
}
Test Test::data = Test(5);
This solution is common for singletons, multitons or similar structures. Notice though, that you can access the field only from the class, not from its instance:
Test test = Test::data;
Your Test is not yet defined completed so how come you create its instance. Sure you can create pointer. Because pointer is incomplete type.
That is why Singleton class and link list have pointers to their reference and not complete object itself.
The memory for the class variables is initialized when an object of the class is made. But if one makes the object of the class in its definition only then during that point the compiler will not be able to initialize the variable of the class as at that point the definition of the class is yet not completed.
Related
In C# I can have two nested classes refer to each other without problem:
public class CFGFile
{
class Setting
{
public Entry Ent;
}
class Entry
{
public Setting Setg;
}
}
However, trying the same thing in C++ causes problems:
class CFGFile
{
class Setting;
class Entry
{
Setting Setg;
};
class Setting
{
Entry Ent;
]
};
I get
"incomplete type not allowed"
at the Setg variable definition, and error
"C2079: 'CFGFile::Entry::Setg' uses undefined class
'CFGFile::Setting'"
when compiling.
I'm using Visual Studio 2017.
Is cross referring not possible in nested classes in C++?
This has nothing to do with nested or not. In C++, you can not cross reference each other for two classes/structs like that. The workaround is that you use either pointer or reference which does not require a complete type definition. In your case, try the following,
class CFGFile
{
class Setting;
class Entry
{
Setting* Setg; // or std::unique_ptr<Setting> Setg;
};
class Setting
{
Entry Ent;
};
};
As suggested by #Ted Lyngmo, std::unique_ptr is the preferred way in modern C++ for applications.
To expand on why this happens, this comes from the fact that when the compiler looks at a struct or class, it needs to be able to determine its exact size, among other things to be able to know how much memory it needs to allocate for instances of these.
In this case, the compiler can't determine the size of Entry because it only knows that a Setting class exists, but it doesn't know its size yet.
Using a pointer, i.e.:
class Setting;
class Entry
{
Setting* Setg;
};
actually solves this problem, because while the compiler still doesn't know anything about Setting, it still knows the size of a pointer (regardless of the pointee's type).
As already mentioned, the "nested" part has no impact on this.
C# - by design - uses reference semantics for classes, thus the provided snippet does not cause circular value depency. OTH c++ prefers value semantics , which would -in turn- result in infinite recursion in the original sample code, if the standard did not ban that kind of code; As implicated in earlier replies, if reference semantics is needed, it should be explicitly expressed in terms of pointer/reference syntax.
Good evening!
I'm writing an Arduino library. Inside it, I want to instantiate an object from another library whose constructor needs to be passed a parameter, but I don't want to hard-code such parameter. I need some guidance about how to do this.
Here's the relevant part of my code so far:
HSBC_CAN.h:
class HSBC_CAN {
public:
HSBC_CAN(uint8_t, uint8_t);
private:
uint8_t _int_pin;
};
HSBC_CAN.cpp:
#include <HSBC_CAN.h>
#include <mcp_can.h>
extern MCP_CAN *canbus_esc;
HSBC_CAN::HSBC_CAN(uint8_t int_pin, uint8_t cs_pin) {
_int_pin = int_pin;
canbus_esc = new MCP_CAN(cs_pin);
}
To be clear, the way to instantiate an object from MCP_CAN class is MCP_CAN foo(int bar), where bar is the chip select pin number for SPI protocol. I want my library to instantiate an object of MCP_CAN class but I need to be able to pass the chip select pin number when instantiating an object from my new class HSBC_CAN. This is the error I get with the above code:
error: request for member 'begin' in 'canbus_esc', which is of pointer type 'MCP_CAN*' (maybe you meant to use '->' ?)
Probably the way I did in my sample code is totally wrong (with the extern keyword and the new operator) but that's just what came out from my mind ATM.
Thanks for the time.
The error message from the compiler is very useful and if you would follow its advice of replacing . with -> it would probably fix your immediate problem. Since canbus_esc is a pointer, you must dereference it before accessing its members or functions. So if it has a function named begin that can be called with zero arguments, you might write:
canbus_esc->begin();
That line is equivalent to:
(*canbus_esc).begin();
Also, get rid of the word extern on the line that defined canbus_esc, or else you will get an undefined reference error for it.
However, I have two issues with the code you have presented: First of all, you are using new, which does dynamic memory allocation. It's a good idea to avoid dynamic memory allocation on small devices like AVRs if you can, since you never know if those allocations are going to fail until you actually run the program (you might be using up too much memory in other parts of your program). Secondly, you defined your canbus_esc at the file scope, so there can only be one of them. This means you can't really create multiple HSBC_CAN objects; the second one will overwrite the canbus_esc create by the first. Although that might be fine for your application, it seems like a needless limitation.
I'd suggest writing your code like this instead:
Header file:
#include <mcp_can.h>
class HSBC_CAN {
public:
HSBC_CAN(uint8_t int_pin, uint8_t cs_pin);
void begin();
private:
uint8_t _int_pin;
MCP_CAN can;
};
Source file:
#include <HSBC_CAN.h>
HSBC_CAN::HSBC_CAN(uint8_t int_pin, uint8_t cs_pin)
: can(cs_pin) // This line constructs the MCP_CAN object
{
_int_pin = int_pin;
}
HSBC_CAN::begin()
{
can.begin(42, 42, 42); // TODO: fix arguments
}
Another idea, which might be better, would be for you to have your HSBC_CAN object take a pointer to an MBC_CAN object and store the pointer as a member variable in the HSBC_CAN class. That option would make a lot of sense if there are multiple devices on the CAN bus that you want to talk to using that MBC_CAN object. You could have multiple classes using a single MBC_CAN object via pointers.
This question already has answers here:
static class member of class's own type [duplicate]
(2 answers)
Closed 6 years ago.
The C++ programming language book mentions like below:
It is not possible to declare new objects of a struct until its complete declaration has been seen. For example:
struct No_good {
No_good member; // error : recursive definition
};
This is an error because the compiler is not able to determine the size of No_good.
But below piece of code is compiling for me.
struct No_good {
static No_good member; // OK: compiling
};
how static keyword allowing compiler to know the size of member. AFAIK static decides the storage class of a named variable.
The reason you can't have a full No_good member inside the No_good class, as pointed out by Francois Moisan is because it would be infinitely recursive and take infinite space.
A No_good* member would be ok because it has a finite space(size of a pointer) and can be null stopping the recursion.
A static member is also ok becuase it is not stored in every instance of No_good but instead shared by all of the instances. It is not technically part of the object but something associated with the namespace of No_good.
Hope this clears it up.
You can think the static variable as a global variable. Only difference is it is under the class's namespace. So if it was a global variable you could reach it like No_good but if it is static you have to type No_good::No_good. You can do that even you never instantiate the class.
The same troubles you can get into with globals you will get with statics as well. You never know which static variable initializes first if they depend on each other you are still in trouble.
The way I experience it, lots of statics usage comes from writing C++ code with C point of view.
class ClassObject {
public:
ClassObject();
virtual ~ClassObject();
private:
int x;
};
int ClassObject::x=10;
Why does it fail to compile?
I think that if static members can be initialized this way, then it should also be possible for non-static ones.
Static members are special. They have a memory allocated to them as soon as the class is defined. And no matter how many objects of that class we create all those objects refer to the same piece of memory.
This is not the case with non static members. Unless you create an object of that particular class, the non static members are not allocated any memory and hence trying to instantiate them in the above way leads to compiler error.
I'm guessing you mean declaring the value used to initialise x for any new ClassObject, i.e. you mean that as equivalent to
ClassObject() : x(10) { }
The problem with your syntax is that the compiler needs to generate code to do that initialisation in every ClassObject constructor; i.e. it can only work if the int ClassObject::x = 10; initialisation is available in the compilation unit that defines all constructors, and any compilation units that generate one implicitly. And the only way to guarantee that is if the value is set inside the class definition, not outside it as you have. (However this is now possible in C++11 - see the link in tacp's comment.)
If we did want to make your syntax work, then we'd need to store the declared value as a hidden static somewhere in a way that any constructors would pick it up and know to use it as the initial value for x. However this static may or may not exist, and the only point we can know that for a constructor in a different compilation unit is at link time. Hence we either generate extra, redundant code to initialise x from this hidden static if it exists (or redundant data) or we mandate link-time-code-generation to solve this, which puts a large burden on the compiler developer. It is possible, yes, but it's simpler all around if this isn't allowed.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the differences between struct and class in C++
class and struct in c++
It looks like that struct can has constructor and destructor and members, and looks very simple, so can we use struct instead class, if not, when shall we use struct with functions when shall we use class ?
https://github.com/developmentseed/node-sqlite3/blob/master/src/database.h#L32
struct Baton {
uv_work_t request;
Database* db;
Persistent<Function> callback;
int status;
std::string message;
Baton(Database* db_, Handle<Function> cb_) :
db(db_), status(SQLITE_OK) {
db->Ref();
uv_ref(uv_default_loop());
request.data = this;
callback = Persistent<Function>::New(cb_);
}
virtual ~Baton() {
db->Unref();
uv_unref(uv_default_loop());
callback.Dispose();
}
};
struct OpenBaton : Baton {
std::string filename;
int mode;
OpenBaton(Database* db_, Handle<Function> cb_, const char* filename_, int mode_) :
Baton(db_, cb_), filename(filename_), mode(mode_) {}
};
There's absolutely no technical reason to prefer one over the other, but I've noticed a certain convention regarding the use of class or struct.
If your datatype is something that is meant to be used by other parts of your program (ie. it's part of the 'interface'), then usually people make it a class to indicate its importance. If the datatype is used only in the implementation of a function or a class and it is not visible outside of a certain scope, then make it a struct.
These are some very rought guidelines, but no one will complain if you don't follow them.
Edit: In C++ there's no real difference between the two, but other newer languages that are inspired by C++ have actually made struct and class different. In C# and in D, for example, class and struct are both used to define datatypes, but they are not the same: struct is implemented such that it should be used for 'small' types.
The only difference is the default access-level (private for a class, public for a struct). Other than that, they are completely interchangeable. You should decide which one you like better, and use that all the time (consistency makes your code more readable).
when shall we use struct with functions when shall we use class ?
It is completely your choice.
There is nothing that one can do with classes and not with structures in C++.
Only difference between structure and class are:
access specifier defaults to private for class and public for struct
inheritance defaults to private for class and public for struct
So just use the one of your choice and stick to using it consistently, do not mix classes and structures.
While as stated by other struct & class does not have any difference besides default access level. However, it's common practice to use structs mostly for data aggregation, as that is what structs are reduced to in C. For example user defined PODs are almost always created as structs in my experience.
The only difference between class and struct is the default accessibility to its members and base classes. For struct, it is public and for class, it is private.
As others have said, the main difference is the default access level of member data and functions, namely private for class and public for structs. The same goes for default inheritance access levels: private for classes and public for structs.
As for when to use which, that is a matter of what is normal for the company to do. In my experience, most companies, and indeed individuals, use structs to hold packets of pure data and classes for storing a collection of functions that operate on its own data and/or structs.
This method is a throwback to C programming where structs can only store data and not functions and so most people like to stick to this definition in C++ too.
Note that it is common to use structs for functors, which would seem to break consistency through the code of structs not containing functions, but since functors usually only overload the () operator we retain some form of consistency anyway. Plus, it saves us having to type public for one function and/or inherited structures... Oh the typing we allow ourselves to avoid ;)
A class is a reference type. When an object of the class is created, the variable to which the object is assigned holds only a reference to that memory. When the object reference is assigned to a new variable, the new variable refers to the original object. Changes made through one variable are reflected in the other variable because they both refer to the same data.
A struct is a value type. When a struct is created, the variable to which the struct is assigned holds the struct's actual data. When the struct is assigned to a new variable, it is copied. The new variable and the original variable therefore contain two separate copies of the same data. Changes made to one copy do not affect the other copy.
In general, classes are used to model more complex behavior, or data that is intended to be modified after a class object is created. Structs are best suited for small data structures that contain primarily data that is not intended to be modified after the struct is created.