I would like to have a class inherit from its enclosed class, as in:
class A : public A::B {
public:
class B {};
};
However, the compiler complains that A::B is not defined:
error: expected class-name before '{' token
class A : public A::B {
That is, A::B won't be usable until the definition of A is complete.
I have tried to preface the above with
class A;
class A::B;
But it doesn't help. How can I get this declared and defined correctly?
Note: Essentially, I am trying to do the opposite of this question.
At the point where you specify the inheritance, the inner class is not yet know. Thus you can't do that. But if the point is to limit the scope, then just use a namespace, e.g. call it detail or implementation.
This is not possible, there is no way to declare inner class without defining the outer class.
Related
Confused by this class
class ParaViewMainWindow::pqInternals : public Ui::pqClientMainWindow
{
public:
pqInternals()
{
}
};
What does it mean?
If it's something like class ParaViewMainWindow: public pqClientMainWindow I know that ParaViewMainWindow inherits from pqClientMainWindow, right?
But here it has ::pqInternals and later
pqInternals()
{
}
What exactly is this doing?
I know :: is the scope operator and I have use it, but never in this situation.
If you look at the definition of the class ParaViewMainWindow, it contains the declaration class pqInternals; (and most likely a member that is a pointer to pqInternals).
This is the definition of that class – its full name is ParaViewMainWindow::pqInternals – and it inherits from Ui::pqClientMainWindow, which is the class pqClientMainWindow in the namespace Ui.
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;
class A {};
class B : private A {
};
class C : public B {
public:
void f() {
A a; // This line causes error, but works when it is in main() function
}
};
int main()
{
C c;
// A a; --> This line works
return 0;
}
I am guessing this has something to do with B inheriting privately from A but cannot put my finger on it.
EDIT: Error is "class A is not visible". Compiled with g++.
name lookup is separate from access checking. and when you inherit from a class, that class' name is injected into the inheriting class' scope. so in class C you pick up the name A but it's not accessible.
one solution is to write ::A a; instead of A a;.
While Alf's answer is correct, I feel that it could be made a bit clearer (or maybe more confusing, who knows). The name of a class is injected into the scope of the class itself. As he mentions access specifiers are only checked after lookup finds what the identifier means. In the code in questions:
class A {};
class B : private A {};
struct C : public B {
void f() {
A a; // This line causes error, but works when it is in main() function
}
};
When processing C::f the compiler sees the identifier A and tries to resolve it. It searches in the scope of C and it is not present, it moves up the hierarchy and does not find it in B, but it finds it inside the base type A (lookup resolves the unqualified A to be ::A::A). In this context the identifier A is resolved to the injected name A inside the base class A of my base class B and access specifiers are checked. The compiler checks whether it can access my base class B, and then whether it can access it's base class A but this one is inaccessible due to the private inheritance and complains that you cannot access the nested name A inside A.
By providing the extra qualification ::A you are directing lookup. In this case, it will find the type A in the global namespace, which is perfectly accessible and it will compile.
Is the following code valid with C++ standard? It's strange that C::B would work because struct B is in A's namespace. But it does compile fine with gcc.
struct A { struct B {}; };
struct C : public A::B {};
struct D : public C::B {};
If this is standard conforming C++, what are reasonable applications for this construct?
Thanks.
Yes, it's valid C++. A class in its own scope (so both B and B::B refer to the same class B), and a class's parent class is in its own scope. So since B is in C's scope and B is in its own scope, C::B refers to B which is A::B.
(Side note: do not confuse a namespace with a scope.)
C++03 §9 paragraph 2 says:
A class-name is inserted into the scope in which it is declared immediately after the class-name is seen.
The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.
For purposes of access checking, the injected-class-name is treated as if it were a public member name.
This is standard conforming C++.
A reasonable application of nested classes (through scope resolution) is the pImpl design pattern (though you can implement it in a way that will not demonstrate nested classes, but here I choose to demonstrate nested classes).
Note: Inheritance is one of the facets that can be confusing but the real concept is the scope resolution of a nested class.
//ExposedClass in Exposed.h
class CExposedClass
{
public:
CExposedClass();
~CExposedClass();
void doThis();
void doThat();
private:
class CXImpl;
CXImpl *pImpl;
};
//ExposedClass Impl in Exposed.cpp
#include "Exposed.h"
class CExposedClass::CXImpl
{
int someData;
};
CExposedClass::CExposedClass():pImpl(new CXImpl()){}
CExposedClass::~CExposedClass(){delete pImpl;}
void CExposedClass::doThis(){}
void CExposedClass::doThat(){}
class defined within the scope of one class is addressed from another scope using scope resolution.
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.