I have this class that compiles in VC14, but when I try to compile in gcc 4.8.5, it doesn't work, I get "error: C was not declared in this scope".
class A
{
};
class B : public A
{
friend class C;
friend class D;
private:
class BB
{
std::list<C> c;
std::list<D> d;
};
};
class C : public B::BB
{
};
class D : public B::BB
{
};
I tried to forward declare "class C" before the definition of class B, but it gives me an error because it doesn't have the same definition as "class C : public B::BB", and I can't put that definition because BB is private... I'm not sure what to do.
Thanks
Forward declarations that use friend are different from other forward declarations. Writing friend class C; within the definition of B declares that there is a class called C in the enclosing namespace (i.e., the global namespace) but does not actually introduce the name C into that scope. Therefore, you can't write something like List<C> because the name C cannot be found. You should do this:
class C;
class D;
class B : public A
{
friend class C;
friend class D;
private:
class BB
{
List<C> c;
List<D> d;
}
}
The namespace-scope declarations actually introduce the names C and D into the global scope. Then, the friend declarations make those classes friends of B.
At the time you do
List<C> c;
List<D> d;
the compiler has no idea what C and D are--you haven't declared/implemented them yet!
You don't have to completely implement them, but you'll need to at least tell the compiler they're class that'll be implemented at some point. You can do that with:
class C;
class D;
Full working example (with some minor fixes like adding semicolons to make it compile): ideone
Related
I have a problem. In the following example, there is a static private member variable called private_b of class A inside namespace a. And then I'm trying to access that variable from class B, which I have declared to be a friend of class A, but it doesn't work, with a compile error from GCC:
error: ‘B* a::A::private_b’ is private within this context
class B;
namespace a {
class A {
private:
static B* private_b;
friend class B;
};
B* A::private_b = nullptr;
}
class B {
public:
void foo() {
B* foo = a::A::private_b; // Error here
}
};
I don't understand why I can't access it, and how to get around this problem. I really want class A to be inside that namespace, and class B doesn't make sense to be inside that namespace. I searched for this on the internet, but couldn't find this exact case, or couldn't find a solution for this case.
friend class B; declared friendship with B in the same namespace a. You may want friend class ::B;.
Note, friend class B; does not refer to the global forward declaration class B, it has own forward declaration class B after the keyword friend.
Consider the following code:
#include <iostream>
class A{
friend class C;
int a{42};
};
class B: private A{
friend class C;
};
class C: private B {
public:
void print() {std::cout << a << '\n';}
};
int main() {
C c;
c.print();
}
According to this answer, the member variable A::a is "present" in all classes, but its visibility differ, i.e. is not visible in B or C unless we make B or C a friend of A. My question is why do I need to make C a friend of both A and B? I would've though the friend declaration in A would suffice. If I remove the friend class C; declaration from either A or B, the code fails to compile.
My question is why do I need to make C a friend of both A and B?
Without B declaring C has a friend, C wouldn't see B as inheriting A. Even though C would see A::a, it would not see B::a.
Indeed:
C inherits B, so anything public in B is accessible from C.
But B inherits privately from A. C being a friend of B makes C see this inheritance.
The access of A::a is private, so even though C sees A as its ancestor, it needs to be a friend of A to see A::a.
If I have something along the following lines
namespace mynamespace
{
class A
{
public:
class B{};
class C{};
};
int foo(B bObject, C cObject); //error
}
When compiled, B and C do not name types. Is there a way so that I can define functions in the namespace that use public nested classes (B and C) defined in Class A?
Use the scope resolution operator. B and C are declared in the scope of class A.
int foo(A::B bObject, A::C cObject);
I have two classes like this:
class B;
class A {
public:
int a, b;
B *b;
public:
int getctxt()
{
b->getctxt1();
}
}
Class B {
public:
int c,d;
A *a;
getctxt1()
{
/* something */
}
}
main()
{
B *b = new B();
A *a = new A();
b->a = a;
a->b = b;
}
But when I try to compile, it says
invalid use of incomplete type ‘struct A’.
Can anyone tell me how to solve this?
Inline class member function definitions are parsed as if they appeared right after the class definition. Of course B isn't defined at that point. So move the member function definition for A::getctxt out of the definition of class A:
class B;
class A { int getctxt(); /* ... */ };
class B { /* ... */ };
int A::getctxt()
{
b->getctxt1(); // at this point, *b has complete type!
return -35;
}
This is the reason why it is recommended to separate your classes in a .h file and a .cpp file. When you write class B;, you are telling the compiler that there is a class called B, but that's it, the compiler does not know what is inside this class. When the compiler reaches the line b->getctxt1();, it knows that b is an instance of B, but it does not know if getctxt1() is a method of B, because that is below. If you are writing all in a single file, you should first write all the declarations, and then all the implementations.
didn't anyone notice Class B syntax error? lowercase class is correct.
and those two public members in A with the same name int b and B *b.
once you remove those and finish class definitions with semicolons, add a void type to the void getctxt1() that is missing it in B.
just define functions as they should be defined. not inline without a reason that you know which is!
If I define a nested class and then create an instance like this:
class A
{
class B
{
...
};
B b;
};
everything is ok. But if I just declare B inside of A and define it outside, I can't create an instance of B, probably because the compiler don't know how much space the instance of B will need. But code is not much readable when you define a class inside another. Is there a way to make this work?
class A
{
class B;
B b;
};
class A::B
{
...
};
Simple, just define class B, then define an instance of it in A.
class B
{
}
class A
{
B memberB;
}
Or you can forward declare it:
class B;
class A
{
B memberB;
}
class B
{
}
Truly nested classes are rarely needed and not very useful at all.
When you use a class type as a member, the concrete class needs to be known. That's why your second case doesn't work. A work around is to use pointer to B:
#include <memory>
class A
{
class B;
std::unique_ptr<B> b;
};
class A::B
{
};