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();
Related
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.
This question already has answers here:
Derived template-class access to base-class member-data
(3 answers)
Closed 5 years ago.
I have created a variable in base class that is a vector of template but I'm not able to access this member from the derived class , can someone explain?
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
/*
*
*/
template <typename T>
class Apple{
protected:
public:
vector<T> vec;
virtual void foo(T node) =0;
};
template <typename T>
class Ball:public Apple<T>{
public:
void foo(T node){
cout<<"hahaha\n";
vec.push_back(node);/* I GET COMPILATION ERROR HERE"vec was not declared in this scope"*/
}
};
int main(int argc, char** argv) {
Ball<int> b;
b.foo(10);
return 0;
}
The member vec is of a template parameter dependent type so the compiler needs some help like:
this->vec.push_back(node);
or use qualified name:
Apple<T>::vec.push_back(node)
Thanks to #Avran Borborah - Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?
Here’s the rule: the compiler does not look in dependent base classes (like B<T>) when looking up nondependent names (like f).
This doesn’t mean that inheritance doesn’t work. ...
You have not created any private members in the base class.
To resolve the error, you can replace the line which produces compilation error with :
Apple::vec.push_back(node);
or
this->vec.push_back(node)
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.
I've got a namespace MyNamespace containing a class MyClass with many static public members functions.
What I need to do, is to build, inside the namespace, a map containing a pointer on every public members functions of the class
Here the code:
#include <iostream>
#include <map>
namespace MyNamespace {
class MyClass;
typedef bool (*fctPtr)(void);
typedef std::map<std::string, fctPtr> fctMap;
};
class MyNamespace::MyClass {
public:
static bool func1(void) { return true; };
static bool func2(void) { return true; };
static bool func3(void) { return true; };
static bool func4(void) { return true; };
};
MyNamespace::fctMap MyFctMap;
void execFct() {
MyNamespace::MyClass obj;
MyNamespace::fctPtr fctMemb;
fctMemb = MyFctMap["func1"];
(obj.*fctMemb)();
}
int main() {
MyFctMap["func1"] = &MyNamespace::MyClass::func1;
MyFctMap["func2"] = &MyNamespace::MyClass::func2;
MyFctMap["func3"] = &MyNamespace::MyClass::func3;
MyFctMap["func4"] = &MyNamespace::MyClass::func4;
execFct();
}
And what the compiler says:
% clang++ draft.cc
draft.cc:29:7: error: right hand operand to .* has non pointer-to-member type
'MyNamespace::fctPtr' (aka 'bool (*)()')
(obj.*fctMemb)();
^ ~~~~~~~
1 error generated.
I don't understand why I got this error neither what to do to resolve the problem. Idea?
Edit: I'm using c++98 and no boost.
Working with a typedef bool (MyClass::*fctPtr)(void) drives me to this kind od error, at map assignment time.
error: assigning to 'mapped_type' (aka 'bool (MyNamespace::MyClass::*)()') from
incompatible type 'bool (*)()'
MyFctMap["func1"] = &MyNamespace::MyClass::func1;
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since the functions you are referencing are static, you don't need the obj class reference. Simply call fctMemb();. You might also consider if you need these functions mapped in such a way, oftentimes you don't need that dynamic aspect to function references in C++ and instead should be using templates.
A pointer to a function is not the same as a pointer to a member function. The important thing to remember is that all (non-static) member function actually have a hidden first argument which is what becomes the this pointer. Therefore a function pointer and a member function pointer can't ever be compatible.
However, you should look into std::function and std::bind:
namespace NyNamespace
{
typedef std::function<bool()> fctPtr;
...
}
MyNamespace::MyClass myObject;
MyFctMap["func1"] = std::bind(&MyNamespace::MyClass::func1, myObject);
The idea is fctMemb(); :-)
fctPtr, as the compiler says, is not a pointer to member type...
Static member functions are not like normal member functions. They have access to class private and protected members, but they are not tied to object instances and thus can't access this pointer nor any non-static members.
Their type is that of normal function pointers and they can't be bound to member function pointers (and normal function pointers is what you have in your code).
You call them like normal functions:
fctMemb();
Btw, the sytax to form member function pointers is different:
struct Foo {
void f() {}
};
void (Foo::* mem_fun_ptr)() = &Foo::f;
I'm trying to create a method in a C++ class that can be called without creating an instance of the class (like a static method in Java), but I keep running into this error: error: expected unqualified-id before ‘.’ token
Here's the .cpp file I'm trying to compile:
using namespace std;
#include <iostream>
class Method {
public:
void printStuff(void) {
cout << "hahaha!";
}
};
int main(void){
Method.printStuff(); // this doesn't work as expected!
return 0;
}
In C++ it's
Method::printStuff();
and you have to declare the method as static.
class Method{
public:
static void printStuff(void){
cout << "hahaha!";
}
};
:: is called the scope resolution operator. You can call the method with . if it's on a class instance, but the instance is not required (it being static and all...).