I have declare a global data and global function,when i try to access in a class compiler throw error as " i cannot appear in constant expression",why?
#include<iostream>
using namespace std;
int i=20;
void fn()
{
cout<<" I am outside class"<<endl;
}
class a
{
public:
int x= ::i; // error is i cannot appear in constant expression
void accessGlobal()
{
::fn(); //fn() is being called
}
};
int main()
{
a obj;
obj.accessGlobal();
}
Your issue is not related with global variables, but with class member initialization.
What you are trying to do with x is in-class member initialization and is supported in C++ since C++11, standard section §12.6.2 :
In a non-delegating constructor, if a given non-static data member or
base class is not designated by a mem-initializer-id (including the
case where there is no mem-initializer-list because the constructor
has no ctor-initializer) and the entity is not a virtual base class of
an abstract class (10.4), then
if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in
8.5;
Solution :
Use a C++11 compiler and add support for C++11 (-std=c++11). See it working here.
If you really can't, do the usual and provide a constructor to initialize your member :
Example :
a() : x(::i) {}
You need to use C++11 standard to compile this code, in previous standards it is forbidden to define non-static variable inside the definition of the class (constructor of the class should do it). Following the old standard you can also try to add static keyword before variable declaration and initialize it after the class definition:
class a {
public:
static int x;
};
int a::x = ::i;
Related
I've encountered this code example and I remembered I've seen it before and I didn't know what it is for and what it does? I've searched on the internet but without luck.
Code:
class C
{
int x; // a non-static variable, implicitly private
public:
C() : x(0) {} // default constructor
// a static member function, which uses a non-static variable perfectly well
static int Incr(C& instance) { return ++(instance.x); }
} g_c;
int main(void)
{
C c2;
return C::Incr(g_c) + C::Incr(c2);
}
What does g_c after the last class bracket means?
} g_c;
Here g_c is declared to be an object of the class type C.
Such construct enables you to create object(s) of unnamed type as:
class //Nameless class!
{
//data members
}obj1, obj2;
In this example, obj1 and obj2 are declared to be objects of a class type which has not been given any name — the class is nameless! In such situation, you cannot declare objects in a conventional sense (i.e Type obj1, obj2; sense). So this construct helps you do that.
You can even derive from other named classes while being nameless (and declaring the objects of the nameless class):
class : public A, public B //Nameless class is deriving from A and B
{
//data members
}obj1, obj2;
In short, this construct ensures that the user wouldn't be able to create more objects than intended, unless some evil programmer uses/misuses/abuses C++11 (or template) as:
decltype(obj1) obj3; //hehe!
Hope that helps!
It's shorthand for:
class C
{
....
};
C g_c;
You declare variables using the format type variable_name;. For example:
A x;
Where A may be the name of a class.
But instead of using a pre-existing class type, you can also define the class at the same time as you declare a variable of the new class's type:
class { ... } x;
or define the class and give it a name:
class A { ... } x;
In C++ it is common to just define the class and give it a name, but leave off the variable:
class A { ... };
but you don't have to leave off the variable.
That's just a way of creating objects of that type of Class. Structs mostly use them to initialize new variables.
Coming from JavaScript and Python, I'm trying to understand the nuances and purpose around C++ class constructors.
In the example below, why is it allowed to initialize attributes without a constructor?
class MyClass {
public:
int a = 1;
int b = 2;
};
Does the default constructor include the above definitions/initializations? What is the difference to the following two examples?:
1.
class MyClass {
public:
int a;
int b;
MyClass(){
a = 1;
b = 2;
}
};
JavaScript/Python style (Is this even possible?)
class MyClass {
public:
MyClass(){
// Some kind of variable declaration and definition like:
// this.a = 1;
// this.b = 2;
}
};
To me having the option of initialization without a constructor sounds like an overkill and is confusing. In both Python and JavaScript one usually declares and initializes all variables from the constructor, and only from there only.
What is the best practice here?
In the example below, why is it allowed to initialize attributes without a constructor?
Because C++11 specifically added that feature. See Member initialization.
Does the default constructor include the above definitions/initializations?
Yes. This code:
class MyClass {
public:
int a = 1;
int b = 2;
};
Is roughly (not exactly) equivalent to this code:
class MyClass {
public:
int a;
int b;
MyClass() : a(1), b(2) {}
};
It is actually possible to use both forms of initialization at the same time, eg:
class MyClass {
public:
int a = 1;
int b = 2;
MyClass() = default;
MyClass(int a) : a(a) {}
};
Per Member initialization:
Non-static data members may be initialized in one of two ways:
In the member initializer list of the constructor.
Through a default member initializer, which is a brace or equals initializer included in the member declaration and is used if the member is omitted from the member initializer list of a constructor.
If a member has a default member initializer and also appears in the member initialization list in a constructor, the default member initializer is ignored for that constructor.
The a member is not specified in the default constructor's member initialization list, so it will be initialized with its default value of 1 when a MyClass object is default constructed.
The a member is explicitly initialized in the converting constructor's member initialization list, so its default value of 1 will be ignored and it will instead be initialized with the caller-provided value when a MyClass object is constructed with an input value.
The b member is not specified in either constructor's member initialization list, so it will always be initialized with its default value of 2.
What is the difference to the following two examples?:
The first example is what you would have to do prior to C++11 (if you are not using the constructor's member initialization list, as shown above).
The second example is not legal in C++. You can't declare members dynamically, and certainly not from inside a constructor. They have to be declared statically in the class declaration itself.
Trying to design some exception-free classes, I have an inheritance structure similar to this, but I have found the noexcept specifier to be of little to no help when working with member functions as the specifier is not scoped as being within the function.
class Base
{
protected:
Base() noexcept {}
};
class Derived : public Base
{
public:
// error: 'Base::Base()' is protected
Derived() noexcept(noexcept(Base{})) : Base{} {}
// error: 'foo' was not declared in this scope
Derived(int) noexcept(noexcept(foo())) {}
// error: invalid use of 'this' at top level
Derived(float) noexcept(noexcept(this->foo())) {}
void foo() noexcept {}
};
Demo
Is this perhaps something that is being improved in C++17? Trying to search for this has yielded no relevant results. For now I've resigned to some very ugly (and possibly incorrect) attempts such as noexcept(noexcept(static_cast<Derived*>(nullptr)->foo())), but this doesn't assist in the case of the base class constructor, which is protected.
Is it even currently possible to declare a noexcept specifier which references a protected base class method like this? noexcept(auto) might be relevant, but of course isn't possible yet. Have I overlooked anything else that would allow me to include this specifier, or do I simply have to omit it in that case?
You can work around it by using an expression where the Base constructor is in scope like this:
struct test_base : public Base {};
Derived() noexcept(noexcept(test_base())) : Base() {}
I believe the reason you cannot use Base() directly is related to this question.
The way protected access specifier works, it allows the derived class
B to access the contents of an object of base class A only when that
object of class A is a subobject of class B. That means that the only
thing you can do in your code is to access the contents of A through
B: you can access the members of A through a pointer of type B * (or a
reference of type B &). But you cannot access the same members through
a pointer of type A * (or reference A &).
It's the same as if you had a member function like this:
void badfunc()
{
B b;
}
You're trying to use Base's constructor directly instead of going through Derived. When you initialize the base in the constructor initialization list, that is a special context that allows you to call the constructor because you're doing it as part of initializing Derived.
This is really multiple questions in one.
About this...
From my understanding, the use of this is supposed to be completely superfluous but compiler support for C++11 is not entirely universal. This should work, according to the C++11 standard:
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(Base::func())) {}
};
Note that base_func() is a non-static member function, but because it appears in an "unevaluated operand" it is okay. From n3337 sec 4.1.1:
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
...
if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
However, some compilers do not support this. You are then forced to use std::declval:
#include <utility>
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(std::declval<Base>().func())) {}
};
About accessibility...
I read through the relevant parts of the standard about "unevaluated operands" and "member access control" and I have come to the conclusion that the standard is a bit ambiguous. It mentions that a protected name can be used only by members, friends, and derived classes. The question is whether unevaluated operands "use" the member names which appear in them. They certainly don't odr-use the member names, and can even use member names if no definition is provided, and this kind of ambiguity is exactly why the term "odr-use" even exists! For example,
int f(); // No definition anywhere in program
int x = sizeof(f()); // Completely valid, even without definition of f
struct X {
X() = delete; // Cannot use this constructor
};
int xsize = sizeof(X{}); // Completely valid
Even though it is somewhat unclear, I have a hard time imagining that the C++ committee could have intended to let you use deleted member functions in unevaluated operands but not inaccessible member functions. However, I am not certain.
Note that the above code compiles without error both with GCC and Clang. However, the following code is does not:
class X {
X(){}
};
class Y {
Y() = delete;
};
bool xokay = noexcept(X{}); // Error!
bool yokay = noexcept(Y{}); // Ok
Both GCC and Clang accept Y but not X, which seems a bit weird to say the least. The following code is accepted by Clang but not GCC, and using std::declval does not help:
class Base {
protected:
void func();
};
class Derived : public Base {
// Clang accepts this, GCC does not.
void func2() noexcept(noexcept(Base::func())) {}
};
What a mess.
Conclusions
The conclusion here is that it seems that there is plenty of inconsistency to go around, and plenty of gaps between current compilers and the C++11 specs.
I have always been under the impression that C/C++ is parsed in 1 pass, therefore, a symbol must be declared before it can be used.
Thus this does not work:
void a()
{
b();
}
void b()
{
}
unless we forward declare void a();
However, I noticed that this does work:
class Foo
{
public:
void a()
{
b();
}
void b()
{
}
};
Why does this work? If C++ is parsed in a single pass through the code then this should not work I would think because the symbol Foo::b() has not been defined when it is called.
The definition of your class:
class Foo
{
public:
void a() { b(); }
void b() { }
};
has the same meaning than:
class Foo
{
public:
void a();
void b();
};
void Foo::a() { b(); }
void Foo::b() { }
This is why the function body sees all the members, as if the class was already completely defined. This is by the ways stated in the C++ standard:
3.3.7/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,
brace-or-equal-initializers of non-static data members, and default
arguments in that class (including such things in nested classes).
The compiler still parses the file in a single pass. But the parsing the grammatical construct is only a part of the larger compilation process, in which applying the context to the parsed grammar production plays also a role (see also this SO question).
There are things called forward references (different from forward declaration)
class C
{
public:
void mutator(int x) { myValue = x; }
int accessor() const { return myValue; }
private:
int myValue;
};
here myValue is accessed before it it declared. C++ does not usually allow forward references but for class members it allows them. It is the compilers job to remember the definition of mutator and accessor until it sees myValue
On the first pass all the class interface is read and thus when the code for function a is compiled it knows that the function b exists in the class Foo
Section 3.3.7 of the C++ Standard includes, among other rules, the statement that
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).
Basically, this requires that analysis of the mentioned contexts, if they appear inline inside the class definition, is deferred until the entire class definition has been processed just as if you had used an out-of-line definition.
A related rule is found in section 9.2:
A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies,
default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise
it is regarded as incomplete within its own class member-specification.
I have a code similar to this:
class AClass {
public:
struct AStruct { };
AClass(){}
private:
const AStruct m_struct;
};
int main() {
AClass a;
}
It throws this compilation error (with Clang LLVM version 5.1):
error: constructor for 'AClass' must explicitly initialize
the const member 'm_struct'
If I specify a C++11 default constructor for struct AStruct, I get the same error:
struct AStruct {
AStruct() = default;
};
However, this is solved by writing a constructor with an empty body:
struct AStruct {
AStruct(){} // fixed
};
Why do I need to specify an empty constructor? Isn't it automatically created with public access for structs?
Why does not the C++11 default constructor solve the problem?
From §8.5 [dcl.init]/7:
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
The default constructor of AClass default-initializes the const member (see below), so that member must have a user-provided default constructor. Using = default does not result in a user-provided default constructor, as can be seen in §8.4.2 [dcl.fct.def.default]/4:
A function is user-provided if it is user-declared and not explicitly defaulted or
deleted on its first declaration.
The member is default-initialized per §12.6.2 [class.base.init]/8:
In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then
— if the entity is a non-static data member that has a brace-or-equal-initializer , the entity is initialized as specified in 8.5;
— otherwise, if the entity is an anonymous union or a variant member (9.5), no initialization is performed;
— otherwise, the entity is default-initialized (8.5).
Stolen from #chris's answer we have this paragraph: §8.5 [dcl.init]/7:
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
We can then construct a completely ridiculous case that illustrates this restriction:
struct Foo {};
int main() {
const Foo f;
}
which fails to compile in clang, as the standard dictates. Your code is simply this, but as a member variable of another class/struct.
We can even do this:
struct Foo {int x = 3;};
int main() {
const Foo f;
}
where all the data is obviously initialized. This last example convinces me that this is a defect in the standard.
The thought was probably something to do with POD types being uninitialized and const, but the wording blocks code that is unrelated. Default constructors in modern C++ are often more than good enough, and forcing Foo(){} is poor form.