What should i do to access member variable of an object? - c++

#include<iostream>
using namespace std;
int main(){
class c1{
int i;
public:
int bv;
void seti(int i){
c1::i=i;
}
int geti(){return i;}
int accessbv(c1 inst1);
};
int c1::accessbv (c1 inst1){
cout<<"here in the base accesing inst1's bv"<<inst1.bv;
}
I want to access inst1's member variable bv.The above code doesnt compile. What should i do?
Also i have observed one thing ,if the class c1's defintion is global it is working the way i want it to. Why is it behaving this way?

Just because the class is local, doesn't mean the rules for defining functions change. The C++ standard even goes as far as to state it explicitly.
[class.local]/2, emphasis mine:
An enclosing function has no special access to members of the local
class; it obeys the usual access rules (Clause [class.access]). Member
functions of a local class shall be defined within their class
definition, if they are defined at all.
"The rules" mentioned above is simply what is stated in the function definition related section of the standard, [dcl.fct.def.general]/2:
... A function shall be defined only in namespace or class scope.
And that's it.

To expand on StoryTeller's answser here is an example of explaining what it means by your comment to his answer:
can you clarify the first statement "An enclosing function has no special access to members of the local class; it obeys the usual access rules (Clause [class.access])." and add something about no functions allowed inside another function rule.
void someFunc() {
class foo {
private:
int x;
public:
int getX() const { return x; }
void setX( int val ) { x = val; }
};
}
Here foo is a local class that is declared in someFunc(). The scope or body of someFunc has no means of accessing foo's internals. Since the above functions are declared & defined within foo's scope this is valid.
Trying to do this:
void someFunc() {
class boo {
private:
int x;
public:
int getX() const;
void setX( int val );
};
// These are illegal. You can not define a function within a function
// even when they belong to a class.
// These two functions can not be defined here because this is
// considered re-declaring them out side of their class within local scope of a function.
// These will give you a compiler error: local function definitions are illegal
int boo::getX() const { return x; }
void boo::setX( int val ) { x = val; }
}
Results in a compiler error.
Here someFunc() has no way of accessing boo's scope through its scope resolution operator for its member variables. It can not access boo::x.
It is illegal to declare a function within a function this can not be done because of the stack pointer for function scope. Functions are not like while & for loops or switch statements which can be nested. A function's scope is a single translation unit within an object file after it's been compiled. You can have an empty scope within a function as that is valid, but you can not declare - define a function within another.

Related

What is the reason to we can not define friend function in local class?

I have a following snippet code of c++. Declared a class inside main() function.
What is the reason to we can not define friend function in local class?
#include<iostream>
int main()
{
class Foo
{
void foo() {} // Ok
friend void Bar(){}; // Error
};
}
There's a practical reason. First and foremost, an inline friend definition cannot be found by either qualified or unqualified lookup. It can only by found by ADL. So if we take the class from your example, put it in global scope and try to call Bar:
class Foo
{
friend void Bar(){};
void foo() {
Bar();
}
};
We'll be notified that Bar was not declared in that scope. So if it was in a local class. You can't call it from the members. You can't call it inside the function. The only way you may call it involves either some hoops or ADL. So the language just doesn't allow for it. It's not deemed a useful feature.
There is no convincing technical reason for this. ADL can't find it, you say? Well, that's basically part of the question: why can't ADL find it? Just extend ADL to make it find it.
One design-level reason for this limitation is probably rooted in the language treatment of unqualified names in friend declarations.
Unqualified names used in friend declarations in local classes refer to names from nearest enclosing non-class scope. This treatment of unqualified names is critically important, since this is the only way local classes can refer to each other (since for obvious reasons, local classes do not have qualified names)
int main()
{
class B;
class A {
int x;
friend B; // refers to local `B`
};
class B {
void foo(A &a) { a.x = 42; }
};
}
This rule is also applied to friend function declarations with unqualified names. C++ does not have local functions, but such friend declarations can still refer to a local non-defining declaration of a function (which is perfectly legal)
void foo() {}
int main()
{
void foo(); // refers to `::foo`
class A {
friend void foo(); // refers to local `foo`, which is `::foo`
};
}
Now, what would you propose should happen when one defines a friend function in a local class (using an unqualified name, of course)? What function is introduced by such a declaration? Into what scope, specifically? By definition, it is not a member of the class, since friend declarations do not introduce class members. It cannot be a member of the nearest enclosing local scope, since that would make it a local function and C++ does not support local functions.
We cannot just uniformly change the behavior of all unqualified names in friend declarations and say that they should now refer to names in the nearest enclosing namespace scope, since that would leave as with no way to refer to local classes (as shown above).
The only way out of this situation is to make only in-class friend function definitions refer to (and define) functions in the nearest enclosing namespace scope. Such functions would only be callable through [modified] ADL (and let's say we are OK with that). But that would mean that we'd have to give different treatment to unqualified names in friend function definitions (as opposed to non-defining friend declarations). This would be rather inelegant and confusing. So, the language authors decided against it.
Note that importance of this might have increased notably after C++14, which gave us deduced auto return types in functions. After that local classes became not even nearly as "local" as they used to be
auto foo()
{
struct S // Local class
{
void bar() {}
};
return S();
}
int main()
{
auto a = foo();
a.bar(); // An object of local class used outside of its original scope
typedef decltype(a) S; // Local type is "stolen" from its original scope
S b; // and used to freely declare objects in a completely
b.bar(); // different scope
}
Because member functions of a local class have to be defined entirely inside the class body and friend function not a member function. We declared friend functions inside class and defined outside of class.
According to cppreference:
Local classes
A local class cannot have static members
Member functions of a local class have no linkage
Member functions of a local class have to be defined entirely inside the class body
Local classes other than closure types (since C++14) cannot have member templates
Local classes cannot have friend templates
Local classes cannot define friend functions inside the class definition
A local class inside a function (including member function) can access the same names that the enclosing function can access.

C++: calling a singleton method results in "expected function body after function declarator"

I am having trouble calling a member function of a singleton class. I have the following
// my_class.hpp
class my_class {
friend struct singleton;
int m_x;
my_class(int x)
: m_x(x) {}
// other private constructors here
public:
const auto& get() const {
return m_x;
}
};
struct singleton {
static auto& instance() {
static my_class x(42);
return x;
}
};
When trying to call singleton::instance().get() outside of main(), the compiler says "expected function body after function declarator". Here is the relevant main file:
singleton::instance().get();
int main() {}
I have found that moving the call inside main everything works fine. I have also found that storing the result outside of main also works fine, like so
auto v = singleton::instance().get();
int main() {}
What I'd like to understand is why calling it outside of main() fails and if there is a workaround that doesn't require storing the result. Thank you.
First of all, it's nothing to do with singletons.
main is the entrance of the program. What the compiler do before main are some declarations: variables, functions, classes. auto v = singleton::instance().get(); is fine, it's a declaration of global variable. Obviously, the compiler take singleton::instance().get(); as a declaraton of function, but actually it's not.
C++ standard says:
3.5 Program and linkage 1 A program consists of one or more translation units (Clause 2) linked together. A translation unit
consists of a sequence of declarations.
This line:
auto v = singleton::instance().get();
is declaration of variable, But this line
singleton::instance().get();
is calling methods instance and get, and compiler treats it as declaration of function which is already declared.

What name lookup rule apply to the name in the definition of static const data member

There is a quote described name lookup applied to data member of a const static data member after the quialified-id of the data member:
sec. 3.4.1/13:
A name used in the definition of a static data member of class X
(9.4.2) (after the qualified-id of the static member) is looked up as
if the name was used in a member function of X.
But we can define in-class static const data member:
class A
{
static const int i = x;//x is a name defined an arbitrary const int
};
Rule from the sec. 3.4.1/13 does not apply to the name x lookup. What rule will be applied actually? Please give a reference to a corresponding clause from standard.
For instance, the following code is valid:
#include <stdio.h>
const int a=5;
class A
{
public:
static const int b=a;//b is unqualified-id of this data-member
};
int main(){ printf("%d\n",A::b); } //5
The following code is also valid:
#include <stdio.h>
class A
{
public:
static const int a=7;
static const int b=a;
};
int main(){ printf("%d\n",A::b); } //7
But the following is invalid:
#include <stdio.h>
class A
{
public:
static const int b=a; //error: a was not declare in this scope.
static const int a=7;
};
int main(){ printf("%d\n",A::b); }
It is unclear what rules applied to lookup of a.
An in-class declaration of a static data member is not a definition even if it includes an initializer. Therefore §3.4.1/13 does not apply to your example.
Name lookup in class scope is defined by the rules of which scopes reach a class scope. §3.3.7/1.1:
The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration,
but also of all function bodies, default arguments,
exception-specifications, and brace-or-equal-initializers of
non-static data members in that class (including such things in nested
classes).
A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No
diagnostic is required for a violation of this rule.
If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no
diagnostic is required.
The purpose of these rules is to allow a member function to access member variables that are declared later in the class. Because the rules don't mention initializers of static data members, name lookup from a static data member defaults to 3.4.1/7:
A name used in the definition of a class X outside of a member
function body, default argument, exception- specification,
brace-or-equal-initializer of a non-static data member, or nested
class definition shall be declared in one of the following ways:
The list essentially boils down to "a name must be a member of the same class, or declared in an enclosing scope." In your first example, a is declared in the enclosing namespace, so it is found. In the second example, a is declared before it is used.
But in the third example, it is used before it is declared which is illegal — and if there was a declaration of some a in the enclosing namespace, it would be undefined behavior due to 3.3.7/1.2.
#include <stdio.h>
const int a=5;
class A
{
public:
static const int b=a; // The quote corresponds to the lookup for a.
// It says that the lookup logic for a is the same
// as the lookup for a name in a member function of A
};
If you have member function, let's make it static for easy comparison, let's see what the lookup for a name in the function looks like.
class A
{
public:
static void fun()
{
b = a;
// The lookup for a:
// 1. A local variable in the function.
// 2. A `static` member of the class.
// 3. A variable in the enclosing namespace.
}
static const int b;
};
When you use
static const int b = a;
the lookup for a will be (2) and (3) from the function foo since a cannot be a local variable.

Private static declaration and subsequent initialization

A .cpp file has a bunch of class definitions . One class has a private static member as follows:
class SomeClass:public SomeParentClass
{
private:
static int count;
};
and right after the class is defined, the count attribute to initialized to zero as follows:
int SomeClass::count = 0;
Coming from the Java/C# world I am having trouble understanding at which point is count initialized to zero? Is it when the SomeClass is instantiated? Also, the class definition has the count type to be int, why does the SomeClass::count has to have an int in front of it?
And my last question is, since the count attribute is private shouldn't its visibility be restricted when it is initialized outside the class definition?
Thanks
Static members of the class are initialized in arbitrary order upon your program's start-up
The static int count; in the class is a declaration of your static variable, while int SomeClass::count = 0; is its definition. All definitions in C++ require to specify a type.
The fact that the definition of the count appears to have occurred in the file scope, the actual scope of the SomeClass::count remains private, as declared.
Is it when the SomeClass is instantiated?
No, you can access it via SomeClass::count (assuming the function has rights to SomeClass's private members) before any instantiations. It's fully usable before you start making objects.
Why does the SomeClass::count has to have an int in front of it?
Well, because it's an int. Think of when you make function prototypes and definitions:
int func (int);
int func (int i) {return 1;} //you still need the int and (int i) here
func {return 1;} //NOT VALID - this is what count would be without int
Since the count attribute is private shouldn't its visibility be
restricted when it is initialized outside the class definition?
Static variable definition is an exception to access specifiers when defined in the normal manner, according to this answer.
The class static variable will behave as if it is initialized to 0 when the program starts. It is independent of class instantiation.
The C++ language requires a type before an identifier in a declaration.
The C++ syntax to initialize a class static variable makes it look like a global, but access to the variable is enforced during compilation.

Defining namespaced member vs free functions without qualification

I sometimes declare classes in nested namespaces and when it comes to defining their member functions, I prefer not to have to qualify each one with these nested namespace names, especially if they are long-ish.
Adding "using namespace " (or, for more precise targetting, "using ::SomeClass") before I define the member functions seems to obviate the need to qualify each definition, but I can't find anywhere in the spec that guarantees this, and I'm worried that it might be a behaviour that only works with GCC. I note that there doesn't appear to be a similar mechanism for skipping the need to add the qualifiers when defining free functions(?).
As an example of what I mean:
Header:
// example.h
namespace SomeNamespace
{
class SomeClass
{
public:
void someMemberFunction();
};
void someFreeFunction();
};
Implementation:
// example.cpp
#include "example.h"
using namespace SomeNamespace;
void SomeClass::someMemberFunction()
{
// OK: seems to define SomeNamespace::SomeClass::someMemberFunction(),
// even though we didn't qualify it with SomeNamespace::
}
void someFreeFunction()
{
// Not what we wanted; declares and defines ::someFreeFunction(), not
// SomeNamespace::someFreeFunction() (quite understandably)
}
int main()
{
SomeClass a;
a.someMemberFunction(); // Ok; it is defined above.
SomeNamespace::someFreeFunction(); // Undefined!
return 0;
}
So my question: is the above way of definining SomeClass::someMemberFunction() legal, and where in the spec is this mentioned? If legal, is it advisable? It certainly cuts down on clutter! :)
Many thanks :)
Perhaps I'm getting this wrong but if you have:
// example.h
namespace SomeNamespace
{
class SomeClass
{
public:
void someMemberFunction();
};
void someFreeFunction();
};
You can also simply write:
#include "example.h"
// example.cpp
namespace SomeNamespace
{
void SomeClass::someMemberFunction()
{
}
void someFreeFunction()
{
}
}
When you define a member-function, the compiler realizes that it is a member-function that must belong to a previously declared class, so it looks that class up, as specified in Section 9.3.5 of the standard:
If the definition of a member function is lexically outside its class
definition, the member function name shall be qualified by its class
name using the :: operator. [Note: a name used in a member function
definition (that is, in the parameter-declaration-clause including
the default arguments (8.3.6), or in the member function body, or, for
a constructor function (12.1), in a mem-initializer expression
(12.6.2)) is looked up as described in 3.4. ] [Example:
struct X {
typedef int T;
static T count;
void f(T);
};
void X::f(T t = count) { }
The member function f of class X is defined in global scope; the
notation X::f specifies that the function f is a member of class X and
in the scope of class X. In the function definition, the parameter
type T refers to the typedef member T declared in class X and the
default argument count refers to the static data member count
declared in class X. ]
Basically, what you are doing is fine. However, there is another (preferable) way to cut down on the clutter when using nested namespaces, or namespaces with long names (or both) - define an alias:
namespace short_name = averylong::nested::namespacename;