This question already has answers here:
error: member access into incomplete type : forward declaration of
(2 answers)
Closed 4 years ago.
I'm trying to figure out how to access member variable of forward declared class though pointer.
My code:
#include <iostream>
class Boo;
class Foo{
public:
int getNum() {
return booPtr->num; //Error: Member access into incomplete type 'Boo'
}
Boo *booPtr;
};
class Boo : public Foo {
public:
Boo() {
booPtr = this;
}
int num = 45;
};
int main() {
Boo boo;
int num = boo.getNum();
std::cout << num << '\n';
}
The error I get :
"return booPtr->num" : Member access into incomplete type 'Boo'
The result I expect :
45
How can I fix this error and what would be more common and safer way to achieve the same thing?
When you access members of a class, the class has to be complete type; only forward declaration is not enough.
You can move the definition of the member function out of the class definition and after the definition of Boo.
class Boo;
class Foo{
public:
int getNum();
Boo *booPtr;
};
class Boo : public Foo {
...
};
int Foo::getNum() {
return booPtr->num;
}
You need to define the member function getNum() where the type Boo is known to the compiler. Hence change the class definition of Foo to
class Boo;
class Foo{
public:
int getNum();
Boo *booPtr;
};
Then comes the definition of Boo, and finally
int Foo::getNum()
{
return booPtr->num;
}
Related
This question already has answers here:
When should you use 'friend' in C++?
(31 answers)
Closed 1 year ago.
From the below code snipped, need to access member function of class A::B. Since class B is private unable to create object for it from non-member function. Kindly help me in getting resolve out of this without moving Class B into public
Code below for reference
A.h
#include <iostream>
class A
{
public:
A();
void Func();
private:
class B;
B *b;
};
A.cpp
#include "A.h"
#include "AB.h"
A::A()
{
b = new B(this);
}
void A::Func()
{
b->Func();
}
AB.h
#include "A.h"
class A::B
{
public:
B(A* a);
void Func();
private:
A* ptr;
};
AB.cpp
#include "AB.h"
A::B::B(A* a):ptr(a)
{
}
void A::B::Func()
{
std::cout<<"Do nothing ";
}
static void call_sample()
{
A::B* tmp;
//access member function of class A::B
}
Error below for reference:
In file included from AB.cpp:2:0:
AB.h: In function ‘void call_sample()’:
AB.h:3:10: error: ‘class A::B’ is private
class A::B
^
AB.cpp:15:4: error: within this context
A::B* tmp;
B is a nested class from A, and it is private, so, as a definition, it is not accessible from the outside. If you need to use B you can decleare B in the public part of A, and then you can use A::B* type.
EDIT:
The original program has multiple files as shown in here
I'm trying to access protected data member in my class from a friend member function of a different class.
I keep getting an access error:
9:32: error: invalid use of incomplete type 'class b' 5:7: error:
forward declaration of 'class b' In member function 'void b::f(a*)':
12:13: error: 'int a::i' is protected 20:47: error: within this
context
This is my code:
// Example program
#include <iostream>
#include <string>
class b;
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
class b{
public:
void f(a* pointer){std::cout<<pointer->a::i<<std::endl;}
};
int main()
{
a a1;
b b1;
b1.f(&a1);
}
The issue is only superficially related to friend. It's rather due to circular dependencies of class definitions and member functions; a needs to know the definition of b because it refers to b::f. But the definition of b::f needs the definition of a, as it refers to a::i. Luckily, definitions of a class and its member functions can be separated from each other.
You can take the following measures to tackle this step by step:
declare class a;
define class b { /* ... */ };, but without defining its member functions (as they need access to a's definition
define class a { /* ... */ };, possibly with inline member function definitions
and finally define b's member functions.
This is how it looks like:
// Step 1:
class a;
// Step 2:
class b{
public:
void f(a* pointer);
};
// Step 3:
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
// Step 4:
void b::f(a* pointer)
{
std::cout<<pointer->a::i<<std::endl;
}
At the point where you try to declare the method of b a friend via friend void b::f(a* pointer);, the class b is incomplete. You cannot refer to members yet. On the other hand, b only needs a forward declaration for a:
// Example program
#include <iostream>
#include <string>
class a;
class b{
public:
void f(a* pointer);
};
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
void b::f(a* pointer){std::cout<<pointer->a::i<<std::endl;}
int main()
{
a a1;
b b1;
b1.f(&a1);
}
Try this. You are trying to reference b::f before class b is defined.
// Example program
#include <iostream>
#include <string>
class a;
class b{
public:
void f(a* pointer);
};
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
void b::f(a* pointer)
{std::cout<<pointer->a::i<<std::endl;}
int main()
{
a a1;
b b1;
b1.f(&a1);
}
This question already has answers here:
Accessing inherited variable from templated parent class [duplicate]
(2 answers)
Closed 7 years ago.
I want to access protected variable in parent class, I have the following code and it compiles fine:
class Base
{
protected:
int a;
};
class Child : protected Base
{
public:
int b;
void foo(){
b = a;
}
};
int main() {
Child c;
c.foo();
}
Ok, now I want to make everything templated. I changed code to the following
template<typename T>
class Base
{
protected:
int a;
};
template <typename T>
class Child : protected Base<T>
{
public:
int b;
void foo(){
b = a;
}
};
int main() {
Child<int> c;
c.foo();
}
And got error:
test.cpp: In member function ‘void Child<T>::foo()’:
test.cpp:14:17: error: ‘a’ was not declared in this scope
b = a;
^
Is it correct behavior? What's the difference?
I use g++ 4.9.1
Hehe, my favourite C++ oddity!
This will work:
void foo()
{
b = this->a;
// ^^^^^^
}
Unqualified lookup doesn't work here because the base is a template. That's just the way it is, and comes down to highly technical details about how C++ programs are translated.
class Foo
{
public:
const int x;
};
class Bar
{
private:
const int x;
};
Output:
test.cpp:10:13: warning: non-static const member ‘const int Bar::x’ in class without a constructor [-Wuninitialized]
Why does Barproduce a warning but Foo doesn't (obviously because of access qualifier, but what is the logic?).
With those definitions, since Foo::x is public, you can validly instantiate a Foo with something like:
Foo f { 0 }; // C++11
or
Foo f = { 0 };
You can't do that for a Bar.
Consider this code:
namespace foo {}
class A
{
class B
{
};
friend int foo::bar( B& );
};
namespace foo
{
int bar( A::B& )
{
}
}
G++ 4.4.3 tells me:
friendfun-innerclass.cpp:21: error: 'int foo::bar(A::B&)' should have
been declared inside 'foo'
But I can't declare:
namespace foo
{
int bar( A::B& );
}
before the class A definition because A::B hasn't been declared. And I can't declare "class A::B" obviously, to declare class B I have to give the definition of class A, and as far as I know the "friend" declarations have to be inside the definition of class A.
What's strange to me is that if I take function "bar()" out of namespace foo everything works fine. It seems counterintuitive to me that having a function inside a namespace or not inside a namespace changes whether the compiler will accept a friend function declaration in the class.
Does anybody know of a way to proprerly structure all the declarations and such to get this to work?
Can't be done the way you want to, because you would have to forward declare a nested class (which you can't) in order to provide a prototype for foo::bar.
As a first attempt to get around this problem, I would probably resort to making foo::bar a function template. That way the compiler will resolve the types after A and B are known.
Test harness:
namespace foo
{
template<class B> int bar(B&);
};
class A
{
class B
{
template<class B> friend int foo::bar( B& );
int n_;
public:
B() : n_(42) {}
};
public:
B b_;
};
template<class B> int foo::bar(B& b)
{
return b.n_;
}
int main()
{
A a;
foo::bar(a.b_);
}
I believe that you need ::foo::bar.
You can't because you can't forward-declare inner classes.
This is a close as you're gonna get.
namespace foo {
class A_B;
int bar(A_B &);
}
struct A
{
class B
{
};
friend int foo :: bar (A_B&);
};
namespace foo
{
struct A_B : public A :: B {
// constructors, delegated if you're C++11 :-)
};
int bar (A_B &)
{
}
}
You lose privatehood of A::B, but if you think about it, that makes sense, or you wouldn't be able to implement foo::bar.
It doesn't look like you can do that. What you can do is forward declare a class with a static member, and the class gets friendship. But any time you use friendship at least take one more look at your design and ask yourself why. It may be fine or there may be a better answer.
namespace foo { class bar; }
class A
{
class B
{
};
friend class ::foo::bar;
};
namespace foo
{
class bar
{
public:
static int run_bar( A::B& )
{
}
};
}
You can't do it because there is no way to write a forward declaration of A::B and hence forward declare foo(A::B&).
However, you can use a trick known as "friend name injection" to declare (and possibly define) a friend function in the class definition. This way you can call that friend function without namespace qualifiers (e.g. bar(b) instead of foo::bar(b)) and argument-dependent lookup will successfully resolve the call:
struct A
{
struct B {};
friend int bar(B&) { // inject bar() into the outer namespace
// implementation here
}
};
namespace foo
{
int foo()
{
A::B b;
return bar(b); // it calls bar(B&) declared in A
}
}