This question already has answers here:
How to add constructors/destructors to an unnamed class?
(3 answers)
Closed last year.
how do you add a destructor to an anonymous class in C++? like in PHP if i want to run something when my class go out of scope it'd be
$foo = new class() {
public $i=0;
public function __destruct()
{
echo "foo is going out of scope!\n";
}
};
but in C++ with normal non-anonymous classes you specify the destructor with ~ClassName(){}, but anonymous classes doesn't have a name! so how do you add a destructor to
class {public: int i=0; } foo;
in c++? i tried using the variable name as the class name, but that didn't work:
class {
public:
int i;
~foo(){std::cout << "foo is going out of scope!" << std::endl;}
} foo;
resulting in
prog.cc: In function 'int main()':
prog.cc:51:31: error: expected class-name before '(' token
51 | class {public: int i=0; ~foo(){std::cout << "foo is going out of scope!" << std::endl;};} foo;
| ^
i also tried specifying just ~ but that didn't work either,
class {
public:
int i=0;
~(){std::cout << "foo is going out of scope" << std::endl;}
} foo;
resulted in
prog.cc:48:30: error: expected class-name before '(' token
48 | class {public: int i=0; ~(){std::cout << "foo is going out of scope" << std::endl;};} foo;
| ^
This cannot be done in C++. However, the real C++ analogue of anonymous classes is called an anonymous namespace:
namespace {
struct foo {
// ... whatever
~foo();
};
}
// ... later in the same C++ source.
foo bar;
Now you can use and reference foos everywhere in this specific C++ source file. Other C++ source files may have their own anonymous namespace, with their own foos, without creating a conflict. The end result is pretty much the same thing as C-style anonymous structs (a.k.a. classes), except that they're not really anonymous, only their namespace is.
Related
This question already has answers here:
Why can I use auto on a private type?
(5 answers)
Closed 2 years ago.
Good morning everybody,
I'm trying to write a member function of a class OUTER_CLASS which returns a unique_ptr to a private class INNER_CLASS defined within the OUTER_CLASS itself. My intent is to write a factory method which returns a reference to an Interface Class which allows to interact with the Implementation Class hided from client. Apart from the design choice, I have a compilation issue: given the following snippet of code, which is a very simplified version of my architecture
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
class OuterClass
{
class InnerClass
{
friend class OuterClass;
public:
void myPrint() { cout << "Inner Class " << a << endl;}
InnerClass(int inA) : a(inA) {};
private:
int a;
};
public:
std::unique_ptr<InnerClass> CreateInnerClass()
{
std::unique_ptr<InnerClass> innerObj;
innerObj.reset(new InnerClass(1));
return innerObj;
}
};
int main()
{
OuterClass obj;
std::unique_ptr<OuterClass::InnerClass> innerObj = obj.CreateInnerClass();
innerObj->myPrint();
}
I get following error:
main.cpp: In function 'int main()':
main.cpp:43:10: error: 'class OuterClass::InnerClass' is private within this context
43 | std::unique_ptr<OuterClass::InnerClass> innerObj = obj.CreateInnerClass();
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:20:11: note: declared private here
20 | class InnerClass
| ^~~~~~~~~~
if instead i use AUTO type deduction, writing
int main()
{
OuterClass obj;
auto innerObj = obj.CreateInnerClass();
innerObj->myPrint();
}
everything is fine...
How is it possible? What am i doing wrong?
Thanks in advance for any answer
Accessibility applies on name, not the type being referred to. So you just can't use the name OuterClass::InnerClass directly in main(), but you can still use the type like calling member functions on the returned object whose type is OuterClass::InnerClass like
obj.CreateInnerClass()->myPrint();
Given auto innerObj = obj.CreateInnerClass(); the name OuterClass::InnerClass is not used directly then it doesn't violate the accessibility check. For the same reason you can use decltype too, even it seems redundant. E.g.
decltype(obj.CreateInnerClass()) innerObj = obj.CreateInnerClass();
class Example{
public:
friend void Clone::f(Example);
Example(){
x = 10;
}
private:
int x;
};
class Clone{
public:
void f(Example ex){
std::cout << ex.x;
}
};
When I write f as a normal function, the program compiles successful. However, when I write f as a class member, this error occurs.
Screenshot:
The error you're seeing is not a root-cause compilation error. It is an artifact of a different problem. You're friending to a member function of a class the compiler has no earthly clue even exists yet,much less exists with that specific member.
A friend declaration of a non-member function has the advantage where it also acts as a prototype declaration. Such is not the case for a member function. The compiler must know that (a) the class exists, and (b) the member exists.
Compiling your original code (I use clang++ v3.6), the following errors are actually reported:
main.cpp:6:17: Use of undeclared identifier 'Clone'
main.cpp:17:25: 'x' is a private member of 'Example'
The former is a direct cause of the latter. But doing this instead:
#include <iostream>
#include <string>
class Example;
class Clone
{
public:
void f(Example);
};
class Example
{
public:
friend void Clone::f(Example);
Example()
{
x = 10;
}
private:
int x;
};
void Clone::f(Example ex)
{
std::cout << ex.x;
};
int main()
{
Clone c;
Example e;
c.f(e);
}
Output
10
This does the following:
Forward declares Example
Declares Clone, but does not implement Clone::f (yet)
Declares Example, thereby making x known to the compiler.
Friends Clone::f to Example
Implements Clone::f
At each stage we provide what the compiler needs to continue on.
Best of luck.
This question already has answers here:
What does the :: mean in C++? [duplicate]
(5 answers)
Closed 9 years ago.
I am learning C++. Now I don't fully understand what this does
Some_Class::Some_Class {
etc...
}
I would do some research for myself, but I'm not sure where to begin or what's it called. Help would be appreciated.
There's no way to say what it is, since the "code" you posted is invalid and ambiguous.
It could be a nested class definition made in out-of-class fashion. When you define nested classes, you can immediately define the inner class inside, as in
class Some_Class { // <- definition of the outer class
...
class SomeClass { // <- definition of the inner class
...
};
...
};
Or, if you prefer, you can only declare the nested class inside, and move the actual definition outside
class Some_Class { // <- definition of the outer class
...
class SomeClass; // <- declaration of the inner class
...
};
class Some_Class::SomeClass { // <- definition of the inner class
...
};
However, for that it has to begin with class/struct, which is not present in what you posted.
Or it could be a definition of member function SomeClass of class Some_Class.
class Some_Class {
...
void SomeClass(int i); // <- declaration of member function
...
};
void Some_Class::SomeClass(int i) // <- definition of member function
{
...
}
But for that it has to include return type and parameter list.
Or it could be a definition of a static member with {}-enclosed initializer
class Some_Class {
...
static int SomeClass;
...
};
int Some_Class::SomeClass { 42 };
But for that it has to include static member's type.
In other words, there's no way to say what it is you posted and what your question is really about.
The :: resolves either a class or namespace.
For example
namespace test1 { int i = 0; }
cout << test1::i << endl;
or
class test2 {
public:
static int i = 0;
};
// after in
cout << test2::i << endl;
You can also add this:
using namespace test1;
cout << i << endl;
You are confused by the scope resolution operator (thanks #Huytard for the link)
:: is the scope resolution operator - it means, that SomeClass method is in Some_Class, given your example -Some_Class::SomeClass
After learning about the fact that nested classes are members of the nesting class and hence have full access to the nesting class's members (at least for C++11, see here), I ran into an issue when trying to create a nested class template:
#include <iostream>
using namespace std;
// #define FORWARD
class A {
// public: // if FooBar is public, the forward declared version works
protected:
enum class FooBar { // line 11, mentioned in the error message
foo,
bar
};
protected:
#ifdef FORWARD
// forward declaration only
template< FooBar fb = FooBar::foo >
struct B;
#else
// declaration and definition inline
template< FooBar fb = FooBar::foo >
struct B{
void print(){ cout << A::i << (fb==FooBar::foo ? " foo" : " not foo") << endl;};
};
#endif
public:
B<>* f;
B<FooBar::bar>* b;
private:
static const int i = 42;
};
#ifdef FORWARD
// definition of forward declared struct
template< A::FooBar fb>
struct A::B{
void print(){ cout << A::i << (fb==FooBar::foo ? " foo" : " not foo") << endl; };
}; // line 41, mentioned in the error message
#endif
int main(int argc, char **argv)
{
A a;
a.f->print();
a.b->print();
return 0;
}
This should (and does) output:
42 foo
42 not foo
Question
Why doesn't this code compile if #define FORWARD is un-commented, i.e. FORWARD is defined?
The error I get (from gcc 4.7.2) is
main.cpp:11:14: error: ‘enum A::FooBar’ is protected
main.cpp:41:2: error: within this context
From an answer to an earlier question I learned that B is a member of A and should have access to the (private) members of it (and it does, it prints A::i). So why isn't A::FooBar accessible in the out-of-class declaration?
Background
This obviously is a minimal example for some other code where header and implementation are split. I would have liked to only forward declare the nested class template B in order to make the interface of class A more readable, as then I could have pushed the template class's implementation to the end of the header file (i.e. the behaviour/setup that one would get by un-commenting the #define FORWARD).
So yes, this is a rather cosmetic problem to have--but I believe it shows that I don't understand what is going on and hence I am curious to learn about the but why?.
You can reduce your example to simply:
class A
{
private:
enum FooBar { foo };
public:
template< FooBar fb = foo >
struct B;
};
template< A::FooBar >
struct A::B
{
};
A::B<> a;
This is legal, as clarified by DR 580, and is accepted by Clang++, so it looks like G++ doesn't implement that resolution yet.
I've reported this as GCC PR 56248 and also reported Clang PR 15209 because Clang doesn't completely implement DR 580 either.
When forward declarations of functions work in a source file (.cpp), why would the same doesn't work for classes ?
Thanks.
// main.cpp
void forwardDeclaredFunction() ; // This is correct
class One ; // Why this would be wrong
int One:: statVar = 10 ;
void
One :: anyAccess() {
std::cout << "\n statVar:\t " << statVar ;
std::cout << "\n classVar:\t" << classVar ;
}
class One {
public:
void anyAccess() ;
static int statVar ;
private:
int classVar ;
} ;
int main (int argc, char * const argv[]) {
One *obj = new One ;
return 0;
}
void forwardDeclaredFunction() {
}
Forward declaration can work for classes too:
class Foo;
class Bar {
public:
Foo *myFoo; // This has to be a pointer, thanks for catching this!
};
class Foo {
public:
int value;
};
The above code shows a forward declaration of the Foo class, using a variable of type Foo* in another class (Bar), then the actual definition of the Foo class. C++ doesn't care if you leave things unimplemented as long as you implement them before using its code. Defining pointers to objects of a certain type is not "using its code."
Quick, dirty reply but I hope it helps.
Edit: Declaring a non-pointer variable of a class thats unimplemented will NOT compile as the replies stated out. Doing so is exactly what I meant by "using its code." In this case, the Foo constructor would be called whenever the Bar constructor is called, given that it has a member variable of type Foo. Since the compiler doesn't know that you plan on implementing Foo later on, it will throw an error. Sorry for my mistake ;).
The forward declaration class One; allows you to refer to the class itself but not to any of its members. You have to put all definitions of class members after the full declaration of the class. (Or inside, of course.)
Place your member declaration of your class before the member implementations.
class One {
public:
void anyAccess() ;
static int statVar ;
private:
int classVar ;
} ;
int One:: statVar = 10 ;
void
One :: anyAccess() {
std::cout << "\n statVar:\t " << statVar ;
std::cout << "\n classVar:\t" << classVar ;
}
You're getting the error message on int One:: statVar = 10 ; NOT on the forward declaration, which is fine.
The compiler needs to know the full definition of the class before you can define static members like that - a forward declaration is insufficient (it needs to be able to confirm that the type is correct from the class definition).
You'll need to move your static attribute definition below the class definition.
The compiler reads stuff from beginning to end, and generates code as it goes. (Some compilers may not do this, but they should behave as if they did.) But before the class is defined, the compiler doesn't know that One::statVar or One::anyAccess should exist, or whether the function is virtual, static, or what. It needs to know that stuff in order to generate code.
when you create 2 class & one function can access data from on class to another class
then it is a friend function
forword declaration is use to know which class in next
class abc;
class xyz
{
data member;
public:
friend void getdata();
other member function
}
class abc
{
data member
public:
friend void getdata();
}