What is considered the best practice for handling this situation?
class A {
private:
std::vector<B> derp;
public:
struct B { ... };
void foo(B b);
}
(The problem is that this code would say "error: use of undeclared identifier 'B'"
I think I could solve the problem by doing something like
class A {
public:
struct B { ... };
void foo(B b);
private:
std::vector<B> derp;
}
But that seems strange and not like the proper solution. Also as a side note, if I were to write that should I write it like this?
struct A {
struct B { ... };
void foo(B b);
private:
std::vector<B> derp;
}
You could use a forward declaration of B before declaring derp if you don't want to move the definition of B before declaring derp.
class A {
public:
struct B;
private:
std::vector<B> derp;
public:
struct B { ... };
void foo(B b);
};
However, from a physical layout perspective, the public section of a class shoud be before its private section. You want the public section to be seen by a user first.
Given that, I think it'll be better to use:
class A {
public:
struct B { ... };
void foo(B b);
private:
std::vector<B> derp;
};
That solves the problem of B not being declared/defined before the declaration of the member variable derp. It also puts the public section ahead of the private section.
Just like variables, you can forward-declare classes and structures. For example, in your case you can do the following:
class A {
public:
struct B;
private:
std::vector<B> derp;
public:
struct B { ... };
void foo( B b );
};
Keep in mind if you forward-declare a class or structure within a class, you need to declare it with the same access level (private/protected/public) as you define it later.
Related
So, I'm in this situation right now. I have two classes A and B. The B is subclass of A and there's also a global object of the B class which is initialized in the main. A function of the A class uses that global object and calls its functions. In what order do I have to write the declarations in order for the compiler to read everything?
I keep getting the same errors whatever I try. Namely:
- (x) does not name a type
- invalid use of incomplete type (x)
- forward declaration of (x)
Code example:
class B;
B* B_GLOBAL;
class A{
public:
void A_function(){
B_GLOBAL->B_function();
}
private:
};
class B : public A{
public:
void B_function();
private:
};
int main(void){
B_GLOBAL = new B;
return 0;
}
Move the definition of A_function below the declaration of B:
class B;
B* B_GLOBAL;
class A{
public:
void A_function();
private:
};
class B : public A{
public:
void B_function();
private:
};
void A::A_function(){
B_GLOBAL->B_function();
}
int main(void){
B_GLOBAL = new B;
return 0;
}
Sorry for the bad title... I think the solution may exist on this site, but I cannot find it.
class A {
};
class B {
private:
int _b;
};
class C {
private:
A a; // a: I want to access _b in b
B b;
};
Let's say I have 3 classes like the code above, now the object a in class C wants to access the member _b in object b. Is there any method to achieve it?
I tried using friend, I wonder if I haven't used it in a proper way, because it made the code very complex, like this:
class B {
private:
int _b;
public:
B() : _b(5) {}
int get_b() {
return _b;
}
};
class A {
public:
int get_a(B& b) {
cout << b.get_b();
}
};
class C {
private:
friend class A;
A a;
B b;
public:
A& get_A() {
return a;
}
B& get_B() {
return b;
}
};
int main() {
C c;
c.get_A().get_a(c.get_B());
}
Thank you in advance.
EDIT
Sorry about the confusing code above, actually I want to implement a compiler using OO style. I think a compiler is made of lexer, parser, and symbol table and other things. So I think the relationship is:
class compiler {
private:
lexer l;
parser p;
symbol_table st;
...
};
And the parser and lexer need to access the symbol_table, that is why this question is put forward. I think this design is resemble to the real compiler "in my opinion", but it seems hard to implement... Any advice is appreciated.
In you example, A must be a friend of B and not of C to let it access members of B:
class A;
class B {
friend class A;
//...
};
// ....
In other terms, it should look like this:
#include<iostream>
using namespace std;
class A;
class B {
friend class A;
private:
int _b;
public:
B() : _b(5) {}
};
class A {
public:
int get_a(B& b) {
cout << b._b;
}
};
class C {
private:
A a;
B b;
public:
A& get_A() {
return a;
}
B& get_B() {
return b;
}
};
int main() {
C c;
c.get_A().get_a(c.get_B());
}
That being said, you should probably reconsider your design to avoid such a strong dependency between your classes and get rid of friends.
Your code looks really confused. I'm not sure what you are trying to do in the second piece of code. The only place you can enable access to members of class B is in class B. You can do this either through making those members public or protected, adding accessor functions for the members or setting another class to be a friend class of class B by adding a friend class declaration inside class B.
Personally I would go with accessor functions as this means you are reducing class to class dependencies. Any class that has internal access to class B, by being made a friend or having direct access to member variables because they are public, is then dependent on the structure of class B.
I'm trying to create a cyclic composition in C++ but I'm dealing with declaration problems. How could I solve them?
This is an example, class A contains a vector of B objects, but class B needs A to be declared first because it's needed in its constructor:
class A {
private:
std::vector<B> sons;
public:
void create_son() {
B obj(this);
sons.push_back(obj);
obj.some_method();
}
};
class B {
private:
A* parent;
public:
B (A* _parent) { parent = _parent; }
void some_method() {}
};
In class A, you use object of class B, so the complete definition of class B is needed. To solve this, put class B definition above class A. At the same time, in class B you work only with pointer to A, so you don't need the complete definition of class A: declaration is enough there.
So, add forward declaration of class A above class B definition.
class A;
class B {
private:
A* parent;
public:
B (A* _parent) { parent = _parent; }
void some_method() {}
};
class A {
private:
std::vector<B> sons;
public:
void create_son() {
B obj(this);
sons.push_back(obj);
obj.some_method();
}
};
You can forward declare pointer types:
class A; // sufficient to fully determine B
class B {
private:
A* parent;
public:
B (A* _parent) { parent = _parent; }
void some_method() {}
};
// now we have B defined, we can define A
class A {
private:
std::vector<B> sons;
public:
void create_son() {
B obj(this);
sons.push_back(obj);
obj.some_method();
}
};
I'm writing a library in C++. I have two classes in my library, A and B. I want to hide the A() constructor from any code that references my library. I also want class B to be able to call the A() constructor.
I come from a C# background and remember little of my C++. In C#, I would simply declare the A() constructor as internal. I've read that the closest way to do this in C++ is a combination of friend declarations and forward-declarations. How do I do this? Here are my three files below:
A.h:
#pragma once
class A
{
private:
A();
};
B.h
#pragma once
class A;
class B
{
public:
A createA();
};
B.cpp:
#include "A.h"
#include "B.h"
A B::createA()
{
A result; //cannot access private member declare in class 'A'
return result;
}
I've tried adding this to A.h:
public: friend A createA();
I've instead tried adding this to A.h with a corresponding forward declaration:
public: friend A B::createA();
I've instead tried adding and extern class B; to A.h and making B a class like this:
public: friend class B;
I'm at a loss.
I think this might be easier if I have the B::createA() function return a pointer to an A object rather than an A object directly, but that won't do in my case. I am emulating a closed API and the API call returns an A object rather than a pointer.
You probably just need to drop the "extern" from your third attempt to turn it into a proper forward-declaration. Try:
A.h:
#pragma once
class B;
class A
{
friend class B;
private:
A();
};
You don't need the external keyword. Make it simple:
// In A.h
class B; // Forward declaration
class A
{
friend class B; // Make all the class B friend
A();
};
// In B.h
class B
{
public:
A createA() {}
};
Live Example.
Unless absolutely necessary, you should have A construct itself (or have a factory that creates A). If you really want B to do it:
class B; // foward declared
class A
{
private:
A() {}
friend class B;
};
class B
{
public:
A CreateA()
{
A a;
return a;
}
};
int main()
{
B b;
A a = b.CreateA();
return 0;
}
Note: You must forward declare B before declaring it a friend in A.
If you want just the function as a friend:
class A;
class B
{
public:
A CreateA();
};
class A
{
private:
A() {}
friend class A B::CreateA();
};
A B::CreateA()
{
A a;
return a;
}
int main()
{
B b;
A a = b.CreateA();
return 0;
}
You can make B a friend of A:
class A
{
private:
A();
friend class B;
};
Suppose I want something of this sort, in one .cpp source file:
class A {
public:
void doSomething(B *b) {};
};
class B {
public:
void doSomething(A *a) {};
};
Is there anyway of doing this without splitting it into two separate files, and without receiving a compiler error (syntax error on doSomething(B *b))
put at the first line:
class B;
If I remember well, you can 'pre-declare' your class B.
class B; // predeclaration of class B
class A
{
public:
void doSomething(B* b);
}
class B
{
public
void doSomething(A* a) {}
}
public void A::doSomething(B* b) {}
Then, your class 'A' knows that a class 'B' will exists, although it hasn't been really defined yet.
Forward declaration is indeed the correct term, as mentionned by Evan Teran in the comments.
forward declare one class before other with
class B;
or
class A;
But still you won't be able to implement
void doSomething(B *b)
using only forward declaration of B. So you have to put definition of doSomething below full class A declaration
Yes. You need a forward declaration:
class B; // add this line before A's declaration
class A {
public:
void doSomething(B *b) {};
};
class B {
public:
void doSomething(A *a) {};
};
The C++ FAQ Lite answers this question and others. I'd seriously considering reading that thing end to end, or getting the book and doing the same.
You can try a forward declaration like
class B;
class A {
void Method( B* );
};
class B{
};
but you will only be able to declare pointer and reference variables for B then. If you want more (like a method that dereferences B* variable) you can provide a declaration only and define methods later in the same file - at the point where both classes declaration is already available.
You need to forward declare B.
class B;
class A
{
public:
void doSomething(B *b) {}
};
class B
{
public:
void doSomething(A *a) {}
};
(And BTW, you don't need the semi-colons after the member function curly braces. :) )
Add another declaration of B before A:
class B;
class A {
public:
void doSomething(B *b) {};
};
class B {
public:
void doSomething(A *a) {};
};