clarification of initialization in C++ - c++

I am really getting confused in following examples:
#include <iostream>
class C {
public:
int a,b;
};
int main() {
C c{3,6};
std::cout<<c.a<<'\n';
std::cout<<c.b<<'\n';
return 0;
}
It works fine and gives the expected outcome. But if I modify the above code like below.
#include <iostream>
class C {
int a,b;
public:
int get_a(){
return a;
}
int get_b(){
return b;
}
};
int main(){
C c{3,6};
std::cout<<c.get_a()<<'\n';
std::cout<<c.get_b()<<'\n';
return 0;
}
In the above program compiler shows multiple errors. Why uniform initialization allowed in first program but not in second? Where I am wrong?

By default c++ class members are private, so without specifying you get a private variable. Because you made the types private you do not get the aggregate-initialization for free anymore so you need to write your own constructor for this class:
class C{
C(int _a, int _b):
a(_a), b(_b)
{}
};
You just need to fix the namespacing for the cout and your code should compile fine: http://coliru.stacked-crooked.com/a/1d69f4f141d2bcd2
From the standard:
[dcl.init.aggr] An aggregate is an array or a class with no user-provided constructors, no brace-or-equal-initializers for non-static data members, no private or protected non-static data members, no base classes, and no virtual functions
In the first code you only had public variables so the code worked because you had an aggregate, making the variable private is what caused the problem because it was no longer an aggregate according to the above definition.

a and b are private in your second example and are therefore inaccessible from outside the class.

You need to move the line int a,b; into the public: scope like the first example.
You also need std:: in front of cout
#include <iostream>
class C {
public:
int a,b; //Make public
int get_a(){
return a;
}
int get_b(){
return b;
}
};
int main(){
C c{3,6};
std::cout<<c.get_a()<<'\n'; //use namespace std::
std::cout<<c.get_b()<<'\n'; //use namespace std::
return 0;
}

In the modified version of the code, you moved the public: label so the a and b data members are no longer public. Hence, they cannot be referenced from outside the class, even not implicitly by an initializer list.

The first code worked because the data members a and b were public, so they could be accessed from outside the class. However, in the second code, they are declared as private, so they cannot be accessed from outside the class. Either declare them as public again, or use a constructor as follows (if you still want them as private):
C(int x,int y) // This is a parameterised constructor
{
a=x;
b=y;
}
And initialise them as C c(3,6);

Related

C++: writing a function for a struct outside that struct? [duplicate]

This question already has answers here:
What are the differences between struct and class in C++?
(30 answers)
Closed 8 years ago.
For classes, you could just say:
class Test{
int a;
Test(int a);
}
Test::Test(int a) {
this->a=a;
}
Function names get "classname::" in front of them when declared outside of class.
How would I do this for structs?
struct Test {
int a;
Test(int a);
}
How would I write the function for this struct Test outside of struct declaration so that it can be only be called by a Test struct?
Same way. Difference between struct and class in C++ is only default visibility of members (private for class, public for struct).
Actually, it's not just function, it's constructor of class/struct Test.
In C++, structs are essentially the same as classes except for their default protection levels: classes default to private, structs to public. To define that function outside of the struct so that it can only be called from a member, declare it as private, then define it as normal:
struct Test {
private:
int a;
Test(int a);
};
Test::Test(int a) {
this->a=a;
}
Additionally, instead of modifying the a member in the constructor body like that, you should use an initializer list. This sets the value of the member before the instance is fully constructed. It's not so important with just an int, but it's a good practice to get in to.
struct Test {
private:
Test(int a) : a(a) {}
int a;
};
How would I write the function for this struct Test outside of struct declaration
Do exactly what you did for the first one. Both are class types, whether you use the class or struct keyword to introduce them.
The only difference is the default accessibility of members and base classes: private if you use class, and public if you use struct.
so that it can be only be called by a Test struct?
If you mean that you want it to be private (as it is in the first example), then you'll have to do so explicitly, since accessibility defaults to public:
struct Test {
int a;
private:
Test(int a);
};
Personally, I'd use the more conventional class if there's anything non-public.
ForEveR is right. Just like in the question you can have a structure member defined like:
struct Test{
int a;
Test(int a);
};
Test::Test(int a) {
this->a=a;
}
point to note, struct members are public by default. class memebers are private by default.

Initialize an array inside Constructor in C++

I have defined an array within a class. I want to initialize the array with some values pre-decided value. If I could do it in definition only then it will be easier as I would have used
class A{
int array[7]={2,3,4,1,6,5,4};
}
But, I can't do that. This, I need to do inside Constructor. But I can't use the same above syntax as it would create a new array inside Constructor and won't affect the array defined in class. What can be the easiest way to do it?
class A{
public:
int array[7];
A::A(){
}
}
You can initialize the array in the constructor member initializer list
A::A() : array{2,3,4,1,6,5,4} {
}
or for older syntax
A::A() : array({2,3,4,1,6,5,4}) {
}
Your sample should compile, using a compiler supporting the latest standard though.
Also note your class declaration is missing a trailing semicolon
class A{
public:
int array[7];
A();
};
// ^
With C++11 you can write this:
class C
{
int x[4];
public:
C() : x{0,1,2,3}
{
// Ctor
}
};

c++ how to write a constructor?

I'm not used to c++ and I'm having a problem writing a constructor.
See this example, is a short version of the code I'm working on:
class B {
public:
B(int x);
}
class A {
public:
B b;
A(){
// here I have to initialize b
}
}
That throws a compiler error since I need to initialize b in A's constructor because B does not have a default constructor.
I think I have do it in the initialization list, but the B(int x) argument is a value I have to calculate with some algorithm, so I don't know how this should be properly done, or if I'm missing something or doing it wrong.
In other language like java I would have a reference to B and initialize it inside the A's constructor after the other code I need to get the value for the initialization.
What would be the right way to initialize b in this case?
Thanks!
You can invoke functions in your constructor initializer list
class B {
public:
B(int x);
}; // note semicolon
class A {
public:
B b;
A()
:b(calculateValue()) {
// here I have to initialize b
}
static int calculateValue() {
/* ... */
}
}; // note semicolon
Note that in the initializer list, the class is considered completely defined, so you can see members declared later on too. Also better not use non-static functions in the constructor initializer list, since not all members have yet been initialized at that point. A static member function call is fine.
You use an initializer list, something like this:
A() : b(f(x)) {}
#include<iostream>
class B {
public:
B(){} // A default constructor is a must, if you have other variations of constructor
B(int x){}
}; // class body ends with a semicolon
class A {
private:
B b;
public:
A(){
// here I have to initialize b
}
void write(){
std::cout<<"Awesome";
}
};
int main(){
A a;
a.write();
}
In C++, if you have a constructor that takes an argument, a default constructor is a must, unlike other languages as Java. That's all you need to change. Thanks.

checking a private variable using a derived class object

below is the small program.
i want to check the value of the private variable x of class A using the object of class B.
is it possible ever?
#include<stdio.h>
#include<conio.h>
#include<iostream>
class A {
int x;
public:
A() {
x=10;
}
};
class B : public A {
public:
int x;
};
int main()
{
B obj;
obj.x=20;
std::cout<< obj.x;
getch();
}
This will output 20, but how can i check the value of x as 10 which is in class A?
i wanted to know whether we can check the value without making x as protected!
You'll have to make the variable protected, or, you can create a protected member method in class A which returns the variable x.
By using the 2nd approach (protected member method or property (is that possible in C++?), class B can read the variable, but cannot change it.
Derived classes cannot see ancestor privates. You can use "protected" for descendents to see the data, but not unrelated classes.
In addition to the private / protected issue, your B::x member over-shades the x of A. So even if both were public, you'd have to write b.A::x. Looks weird, but works (see code below) ....
This is syntax-wise. You should tot do this, of course, as everybody here say. use protected members with meaningful names, and accessor functions
class A {
public:
int x;
};
class B: public A {
public:
int x;
void f() { std::cout << "B::x=" << x << ", A::x=" << A::x << '\n'; }
};
int main()
{
B b;
b.A::x = 10;
b.x = 20;
b.f();
}
output:
B::x=20, A::x=10
You can not examine the value of private members of base class. So: add an accessor in A or make A::x protected.
Make x in A protected and write a method in B that looks something like this:
int getAX(){
return A::x
}
You shouldn't.
Since your A class tells the member is private, nobody but A can access it.
If B is-an-A, the same rule is valid: A::x is still inaccessible.
Your wanting to access it means you either need a different kind of A (i.e. make A::x public), or you want the wrong thing.
Well, if you really want to know if it's possible: it is. public, protected and private are only compile time checks. One possible option to circumvent them during runtime is the following:
#include <iostream>
class A{
int x;
A() : x(10){}
};
struct pubA{
int x;
};
int main(){
A a;
// evil casting
pubA* pa = reinterpret_cast<A*>(&a);
std::cout << pa->x << std::endl; // should print 10
}
That said, don't do it. There is a reason for these keywords. (The above code is untested, 'caus I'm writing from my iPod. If reinterpret_cast doesn't work, use old C-style cast: pa = (pubA*)&a.)

C++ inheritance: scoping and visibility of members

Can you explain why this is not allowed,
#include <stdio.h>
class B {
private:
int a;
public:
int a;
};
int main() {
return 0;
}
while this is?
#include <stdio.h>
class A {
public:
int a;
};
class B : public A{
private:
int a;
};
int main() {
return 0;
}
In both the cases, we have one public and one private variable named a in class B.
edited now!
In both the cases, we have one public
and one private variable named a in
class B.
No, thats not true.
In the first case, you can't have two identifiers with the same name in the same scope. While in the second case, B::a hides A::a, and to access A::a you have to fully qualify the name:
b.a = 10; // Error. You can't access a private member.
b.A::a = 10; // OK.
Because B::a hides A::a in the second example. You can still access it, but it needs explicit qualification for the compiler to figure out you are asking for the member of parent class with the same hame.
In the first example both a's are in the same scope, while in the second example the scopes are different.
Class B in the first example is not valid because C++ cannot distinguish members by their access specifiers (public/private/protected). However, namespaces are a way for C++ to distinguish members. In class B in the second code you don't have a "public a" and a "private a", you have B::a and A::a.
Even if declaring members of the same name/signature with different access specifiers was allowed, there would be no way to address the correct member.
The first isn't allowed because it leads to ambiguous definitions. In the 2nd, although you do have both a public and a private a integer variable, you've hidden A::a inside your B class. The compiler knows implicitly what you want because there is a way to explicitly access a hidden variables.
I also believe that it boils down to name mangaling: storage specifiers don't end up as part of the actual name. I could be wrong on this however.
The easiest way to illustrate why one is allowed and why the other isn't is to look at how the compiler would compile a member function that uses each variable.
Inside your class b:
class b {
int a;
public:
int a;
void myMethod()
{
a = 10; //what a should the compiler use? Ambiguous, so the compiler sez BZZT.
}
}
For the 2nd example:
class A
{
public:
int a;
}
class B: public A
{
private:
int a;
void someMethod()
{
a = 10; //implied that you are using B::a (which may be a programmer error)
}
}