As a rule of thumb on forward declaration (from "API Design for C++", p. 214), I only include the header of a class if I:
use an object of that class as a data member in my own class, or
inherit from that class.
In all rest cases I just forward declare the class.
However, I recently used by accident as a data member of a class a forward declared enum class, and it compiled.
Is this indeed ok to use, or a just an accidental hack (and I actually need the header with the definition of MyEnum)?
// test.hpp
enum class MyEnum;
class A {
MyEnum myenum;
};
A forward declared enum class has a specified underlying type. If not explicitly specified it is int. Because of that the storage size of the enum is known, even if it's only forward declared, so using it as a member is not a problem.
Related
I have a public header that has class X. X has a private member of nested type U::V. As I understand, normally, you just forward declare the types but I cant forward declare nested type. U::V is in a private header so I cannot #include them from a public header. What do I do to have X know of class U::V?
Summary of my code:
// in include/mylib/box.h
class X {
public:
X();
//...
private:
U::V stuffs; // how do I have this declaration work?
};
// in some private file
class U {
class V{
// ..
};
};
What do I do to have X know of class U::V?
Only way to have a member of type U::V in X is to define the type U::V before defining X.
You can avoid storing the member directly by using the PIMPL idiom. In short, you would store a pointer to a forward-declared type.
This question was answered by Adam Rosenfield here.
You'll have to un-nest at least one of the nested classes
I just realized this happens because I got an incomplete class definition, not because it's a nested class. Thanks, everyone.
i got below compilation problem, while defining member function. is there a way to define member function before class declaration but with forward declaration?
error: invalid use of incomplete type ‘class GetErrorLogInterfaceTest’
class GetErrorLogInterfaceTest; // forward declaration of class
void GetErrorLogInterfaceTest::initializeJsonFile() { // member function definition
}
class GetErrorLogInterfaceTest : public ::testing::Test {
public:
void initializeJsonFile(); // member function declaration
}
No. It is not possible to define member functions of incomplete classes. It is only possible to define member functions of those classes that have been defined. A forward declaration is not sufficient.
The standard says in [class.mfct]:
A member function may be defined (11.4) in its class definition, in which case it is an inline member
function (10.1.6), or it may be defined outside of its class definition if it has already been declared but not
defined in its class definition. ...
Now, the rule does not say that member functions may only be defined in these two places, so unless you know that standard has no other rule which allows a member function definition somewhere else (which it doesn't, as far as I know), then this by itself isn't technically complete information.
However, the paragraph continues
... Except for member function definitions
that appear outside of a class definition, and except for explicit specializations of member functions of class
templates and member function templates (17.8) appearing outside of the class definition, a member function
shall not be redeclared.
Note that a member function shall not be redeclared within the class definition. If the member function were defined before the class definition, then the function declaration within the class definition would be a redeclaration, and would violate this rule.
No. The standard covers this trivial aspect as well.
From CPP draft (N4713)
12.2.1 Member functions [class.mfct]
A member function may be defined in its class definition, in which case it is an inline member function, or it may be defined outside of its class definition if it has already been declared but not defined in its class definition.
So the class definition is first necessary to define the member function in either one of the ways mentioned above.
I'm regular to write in java,
and I'm a little bit confused about static nested class in C++.
I'm trying to declare a static class, but I get an error :
class D
{
public:
static class Listener
{
public :
void foo()
{
cout << "foo" <<endl;
}
};
};
And I getting following error
"storage class can only be specified for objects and functions"
(I'm using an online compiler).
The correct terminology would be "static nested class".
Static nested classes in Java are like normal nested classes in C++, so just drop the static and it should work fine.
Non-static ones like in Java would be a bit harder to emulate in C++, because there is no compiler magic to automatically provide the context of the outer class. You would have to work around the issue by storing a reference to the outer class in the inner class, initialising it in the constructor of the inner class, and accessing members of the outer class explicitly via the reference.
Classes in C++ are merely nested type definitions, so only act as namespaces for nested type definitions.
If you declared a class type definition as static anywhere (nested or not nested), you'd get a compiler warning and it will be stripped off. Classes cannot have storage class specifiers and static has been repurposed something different inside a class. This is because class types don't have storage at all and are just templates (so linkage doesn't make sense; they don't even survive that far), and method definitions are compiler directives that the compiler is able to concretise when it chooses, but just so easily can exclude from the assembly output, unlike regular functions, which are guaranteed to be present when placed in another translation unit, so all class members are effectively inline (unless static, then they need to be explicitly made inline to provide an inline definition). static used on a class inside a class is redundant because classes nested are implicitly static in this sense.
When you instantiate the parent class, it does not include the nested class because this is just a compiler directive. You have to include an object of the class as one of the members, where the class type definition is in scope:
class c {
public :
int i;
class s f; //not allowed
class s;
class s k; //not allowed, still has forward declaration type
class s {
public:
int j;
};
s p; // allowed
};
You can forward declare a nested class in a class but a member cannot be defined with a forward declaration incomplete type unless it is a pointer or reference to it, but it can be with an incomplete type if the type has been completed above it in the scope.
Unlike a namespace however, you cannot access non-static members of the parent class from the nested class (this type of static and non-static do not exist in namespaces anyway). This is because the nested class is instantiated separately to the parent class and the parent class may never be instantiated. It just so happens that the programmer may initialise the nested object in the parent object, just as it could store it in a pointer in the object or a local pointer and initialise it on the heap, but at the object level, they are separate objects and where their type definitions are is irrelevant. If you called a non-static member of the parent class, the compiler would have to pass an object of the parent class to it. It could theoretically use the parent class type definition to determine the offset it will be at in memory for the member it fills, but it might not always be a subobject of a parent object. In order for this functionality to be allowed, the compiler would have to throw an error if the subclass is instantiated without the parent class being instantiated and it being assigned as a subobject of the parent subobject.
I'm trying to declare class as the following:
class MyClass: MyBase;
But I can't because compiler is swearing.
error: expected ‘{’ before ‘;’ token
I'm trying to find a class name declaration to clarify this aspect. But I can't. I'm looking for this in the clause 7 (Declarations) of the c++ working draft.
If you just want to declare the MyClass class, then
class MyClass;
is enough. It tells the compiler that the class MyClass exists, and you can now declare pointers or references to MyClass.
If you want to define the class, then you need to full definition.
About standard(n3797):
9.1 Class names:
A class declaration introduces the class name... A declaration
consisting solely of class-key identifier; is either a redeclaration of
the name in the current scope or a forward declaration of the
identifier as a class name. It introduces the class name into the
current scope.
10 Derived classes:
A list of base classes can be specified in a class definition...
So, you can just tell the compiler: "Oh, I will define this class later". If you need to know the "structure" of the class then you need to define it.
Give definition in this way :
class MyClass: MyBase
{
//////
};
If you only want to declare then do in this way :
class MyClass;
I have a basic question that has bothered me for sometime.
When using a Class within a Class I can define the header of the Class I want to use in the header file. I have seen two ways of doing this and would like to know the difference between the two methods?
ex1
#include "ClassA.h"
class ClassB {
public:
ClassB();
~ClassB();
ClassA* a;
};
#endif
ex2 Here is the other way of doing it. The ClassA Header would be defined in ClassB source file.
class ClassA;
class ClassB {
public:
ClassB();
~ClassB();
ClassA* a;
};
#endif
What are the differences with these two methods?
The comlpete layout of the classA is known to the compiler when you include the class definition.
The second syntax is called Forward declaration and now classA is an Incomplete type for the compiler.
For an Incomplete type,
You can:
Declare a member to be a pointer or a reference to the incomplete type.
Declare functions or methods which accepts/return incomplete types.
Define functions or methods which accepts/return pointers/references to the incomplete type (but without using its members)
But You cannot:
Use it as a base class.
Use it to declare a member.
Define functions or methods using this type.
Use its methods or fields, in fact trying to dereference a variable with incomplete type.
So Forward Declaring the class might work faster, because the complier does not have to include the entire code in that header file but it restricts how you can use the type, since it becomes an Incomplete type.
The second method only allows you to create pointers to ClassA, as it's size is unknown. It may however compile faster as the header for the full definition for ClassA is not included.
The latter is a forward declaration. This way you can declare a pointer or reference to a class, even though you have not yet fully declared it. This can be used to resolve cyclic dependencies. What if, in your first example, A also wants to use a pointer to B. This wouldn't work, because when A is declared, B is not known yet. To solve this, you can use a forward declaration to tell the compiler that there is a class B, and you will tell it later what it looks like.