Local Classes in C++ - c++

I am reading "Local Classes" concept in Object-oriented programming with C++ By Balagurusamy (http://highered.mcgraw-hill.com/sites/0070593620/information_center_view0/).
The last line says "Enclosing function cannot access the private members of a local class. However, we can achieve this by declaring the enclosing function as a friend."
Now I am wondering how the highlighted part can be done?
Here is the code I was trying but no luck,
#include<iostream>
using namespace std;
class abc;
int pqr(abc t)
{
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know the code looks erroneous, any help would be appreciable.

Your friend statement is fine.
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
friend int pqr();
};
return abc().x;
}
int main() {
cout << "Return " << pqr() << endl;
}
Edit:
IBM offers this explanation for the issue raised in the comments:
If you declare a friend in a local class, and the friend's name is unqualified, the compiler will look for the name only within the innermost enclosing nonclass scope. [...] You do not have to do so with classes.
void a();
void f() {
class A {
// error: friend declaration 'void a()' in local class without prior decl...
friend void a();
};
}
friend void a(): This statement does not consider function a() declared in namespace scope. Since function a() has not been declared in the scope of f(), the compiler would not allow this statement.
Source: IBM - Friend scope (C++ only)
So, you're out of luck. Balagurusamy's tip only works for MSVC and similar compilers. You could try handing off execution to a static method inside your local class as a work-around:
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
static int pqr() {
return abc().x;
}
};
return abc::pqr();
}

There seems to be a misunderstand about local classes.
Normally there are here to help you within the function... and should NOT escape the function's scope.
Therefore, it is not possible for a function to take as an argument its own local class, the class simply isn't visible from the outside.
Also note that a variety of compilers do not (unfortunately) support these local classes as template parameters (gcc 3.4 for example), which actually prevents their use as predicates in STL algorithms.
Example of use:
int pqr()
{
class foo
{
friend int pqr();
int x;
foo(): x() {}
};
return foo().x;
}
I must admit though that I don't use this much, given the restricted scope I usually use struct instead of class, which means that I don't have to worry about friending ;)

I have no solution for the friend thing yet (don't even know if it can be done), but read this and this to find out some more about local classes. This will tell you that you cannot use local classes outside the function they are defined in (as #In silico points out in his answer.)
EDIT It doesn't seem possible, as this article explains:
The name of a function first introduced in a friend declaration is in the scope of the first nonclass scope that contains the enclosing class.
In other words, local classes can only befriend a function if it was declared within their enclosing function.

The friend int pqr(abc); declaration is fine. It doesn't work because the abc type has not been defined before you used it as a parameter type in the pqr() function. Define it before the function:
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// Class defined outside the pqr() function.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
// At this point, the compiler knows what abc is.
int pqr(abc t)
{
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know you want to use a local class, but what you have set up will not work. Local classes is visible only inside the function it is defined in. If you want to use an instance of abc outside the pqr() function, you have to define the abc class outside the function.
However, if you know that the abc class will be used only within the pqr() function, then a local class can be used. But you do need to fix the friend declaration a little bit in this case.
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// pqr() function defined at global scope
int pqr()
{
// This class visible only within the pqr() function,
// because it is a local class.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
// Refer to the pqr() function defined at global scope
friend int ::pqr(); // <-- Note :: operator
} t;
t.xyz();
return t.x;
}
int main()
{
cout<<"Return "<<pqr()<<endl;
}
This compiles without warnings on Visual C++ (version 15.00.30729.01 of the compiler).

Related

Namespace's class's friend that is not declared and defined in the namespace

Is it right to do so:
void f();
namespace ns
{
class C
{
int m;
friend void ::f();
};
}
void f()
{
ns::C c;
c.m = 2;
}
?
The code is compiled successfully in VS. But I can't find anything about qualifying a namespace for a friend declaration in the standard. Is it even legal? Can someone provide the link or the quote from the standard?
Yes it's legal.
A namespace is little more than a way of adding another layer of descrimination for functions, classes, &c..
Any function can be marked as a friend inside a class, even if that class is in a different namespace to the function. The function could be in a namespace too.
There's no specific section in the standard on this, but it's a corollary of the standard. This reference is a starting point: https://en.cppreference.com/w/cpp/language/namespace

C++'s double colon used after a class name instead of a namespace

I am trying to understand a c++ program listed here. I am confused about the second use of double colons on lines 86-87:
using TransformType = itk::AffineTransform< ScalarType, Dimension >;
TransformType::Pointer transform = TransformType::New();
It looks like TransformType is a user-defined type. How would one use it before New()? I heard that the double-colon is to be used following a namespace, but here, TransformType is a type (namely class) rather than a namespace. Can someone clarify --- should double colon be always used after a namespace in C++? Would it possible to use a dot (like in Java) instead?
You use the scope resolution operator (::) to name something in a namespace, or in a class, or in a scoped enum; this is called qualified lookup.
#include <iostream>
namespace N
{
int x = 0;
}
int main()
{
std::cout << N::x << '\n';
}
Using it with a class usually means you're referring to some static member, because otherwise you'd generally be using objectInstance.member instead.
#include <iostream>
class C
{
public:
static int x;
}
int C::x = 0;
int main()
{
std::cout << C::x << '\n';
}
Though, within a non-static member function, there are still uses for ::, such as disambiguating between names that exist concurrently in different bases.
class Base
{
public:
void foo() {}
};
class Derived : public Base
{
public:
void foo()
{
// Do base version (omitting Base:: will just call this one again!)
Base::foo();
// Now maybe do other things too
}
};
int main()
{
Derived obj;
obj.foo();
}
… or for naming a non-static member in a scenario where an object context is not required:
#include <iostream>
class C
{
public:
int x;
}
int main()
{
std::cout << sizeof(C::x) << '\n';
decltype(C::x) y = 42;
}
It's needed with scoped enums because, well, they're scoped; that's the whole point of them. They don't leak into the surrounding scope but have their own which as a result you need to specify specifically.
enum class E
{
Alpha,
Bravo,
Charlie
};
void foo(E value) {}
int main()
{
foo(E::Alpha);
}
Some languages let you access static members of classes with the type name followed by ., just like you'd access non-static members of classes with the object name followed by .. C++ is not one of those languages.
By the way, this is legal:
#include <iostream>
class C
{
public:
int x = 42;
};
int main()
{
C obj;
std::cout << obj.C::x << '\n';
// ^^^ what?!
}
Adding scope resolution to x here is not necessary, because the language already knows from the obj. that you're asking for a member of a class C. But you can still add it if you want. It's just usually "done for you" in this case.

Member is inaccessible

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.

How to make a function only seen by one function in c++?

How could I make a function only seen by the function that calls it?
define the function I want to hide as private function is not enough, as it could still be seen by other public functions in the class.
Now I use lambda expression to define anonymous function inside function. Is there any better solution?
Aside from using a lambda (which you've rejected), you could implement your function in its own compilation unit, and code the supporting function in an anonymous namespace within that compilation unit.
But that supporting function would be outside the class, so you'd have to pass it all the parameters it needed. That could become unwieldly though no worse than a long lambda capture list.
You can use a function object. For example(you can compile this, even in C++03):
#include <iostream> // only for output
class foo{
int bar(){return 0;} // Only foo can see this
public:
int operator()(){
return bar();
}
};
class baz{
public:
foo do_foo;
};
int main(){
baz a;
std::cout << a.do_foo() << std::endl;
}
the method bar is only visible by a foo.
P.S.: If you need foo to access members of baz, make it a friend.
A simmilar approach to cassiorenan would be to use static class functions and friends.
Something like this:
void Boss();
class Worker {
static void Test(){ return;}
friend void Boss();
};
void Boss(){
Worker::Test();
}
Though why would you want to do this, I don't know.
It is possible to define function inside a function without lambdas. Just define a struct that contains required function. This approach is not much better than using lambda, but at least this is straightforward and works with older compilers too.
int func() {
struct {
int hiddenFunc() {
return 1;
}
} h;
int a = h.hiddenFunc() + h.hiddenFunc();
return a;
}
As a slight variation from cassiorenan's solution, you could use a class containing one public static function (the visible function) and one static private function that could only be called from there. To avoid creation of objects of that class, it is enough to put a private constructor.
EDIT:
Per cassiorenan's comment, I can see that OP really needs methods and not functions. In that case, I would still use a dedicated class in a anonymous namespace to ensure it is not visible from elsewhere (even if my example is single file ...) friend to the class really used. So in below example, bar is the business class that would have a method with an externally hidden implementation (here relay_method), and foo is dedicated to the hidden method called with a pointer to the real object. In real world, the whole anonymous namespace and the implementation of the hidden method should be in the implementation file bar.cpp.
That way, the real implementation function priv_func can only be called from a bar object through bar::relay_method() and foo::bar_func(bar &).
#include <iostream>
class bar;
namespace {
class foo {
private:
static int priv_func(int i) {
return i * i;
}
foo() {}
public:
// only useful if true functions were needed
/* static int pub_func(int i, int j) {
return priv_func(i) + priv_func(j);
}*/
static void bar_func(bar& b);
};
}
class bar {
int x;
int x2;
public:
bar(int i): x(i) {}
void relay_method() {
foo::bar_func(*this);
}
friend class foo;
int getX2() const {
return x2;
}
};
void foo::bar_func(bar& b) {
b.x2 = foo::priv_func(b.x);
}
using namespace std;
int main() {
/* int i = foo::pub_func(3,4);
cout << i << endl;
// foo::priv_func(2); error access to private member of class foo
// foo f; */
bar b(2);
b.relay_method();
cout << b.getX2() << endl;
return 0;
}

C++ - Calling a function inside a class with the same name as the class

I was trying to write up a class in c++, and I came across a rather odd problem: calling outside functions inside of a class that have the same name as the class. It's kinda confusing, so here's an example:
void A(char* D) {
printf(D);
}
class A
{
public:
A(int B);
void C();
};
A::A(int B) {
// something here
}
void A::C() {
A("Hello, World.");
}
The compiler complains at the second to last line that it can't find a function A(char*), because it is inside the class, and the constructor has the same name as the function. I could write another function outside, like:
ousideA(char* D) {
A(D);
}
And then call outsideA inside of A::C, but this seems like a silly solution to the problem. Anyone know of a more proper way to solve this?
::A("Hello, world.");
should work fine. Basically it is saying "use the A found in the global namespace"
Use the scope resolution operator :: to access the name from the global scope:
void A::C() {
::A("Hello, world.");
}
I suggest you use namespaces. Put your class in a different namespace than the function.
namespace my_namespace1
{
void A() {}
}
namespace my_namespace2
{
struct A {};
}
int main()
{
my_namespace1::A();
my_namespace2::A my_a;
}
Of course, the real question is, why do you have a class and a function with a different name? A good easy rule is to make classes named WithABeginningCapitalLetter and functions withoutOne. Then you will never have this problem. Of course, the STL doesn't do this...