class A{
private : string a[3];
public : A();
void ShowA();
}
A::A(){ string a[3] = {"aa","bb","cc"} }
void A::ShowA(){
for(int x=0;x<=2;x++){
cout<< a[x];
}
}
int main(){
A a;
a.ShowA();
return 0;
}
In this code, I think the output is aabbcc but there is nothing. Just blank is existed.
Could you tell me why it happens and how to fix it.
Cheers guys.
As the comments tell you, you are creating a local variable a inside your constructor, instead of setting the value of the attribute a. You can set the value of a in member initializer list.
The code becomes
#include <iostream>
#include <string>
using namespace std;
class A {
private:
string a[3];
public:
A();
void ShowA();
};
A::A() : a{"aa"s, "bb"s, "cc"s} {}
void A::ShowA() {
for(int x = 0; x <= 2; x++) {
cout << a[x] << std::endl;
}
}
int main() {
A a;
a.ShowA();
return 0;
}
Note: The 's' after the "aa", "bb" and "cc" strings is a string literal. It is not really necessary in this case, since the compiler know you are creating an array of std::string objects.
You are re-defining the string "a" in the constructor, you should simply assign it in the constructor instead of using the "string" type again. If you give the type again it creates a local variable available in the scope of the constructor only.
Related
I really didn't know what to put as the title for this so ignore that. I also don't know how to describe the question so here is my issue.
#include <iostream>
#include <vector>
class ClassB {
public:
//LOOK AT THIS PART
int value;
char letter;
ClassB(char t, int v) {
letter = t;
value = v;
}
};
class ClassA {
private:
ClassB* ptr;
public:
ClassA(ClassB n) {
ptr = &n;
}
ClassB* getPtr(){
return ptr;
}
};
int main() {
std::vector<ClassA> objects;
for(int i=0;i<4;i++) {
objects.push_back(ClassA(ClassB('a',i)));
}
std::cout << "Value: " << objects[1].getPtr()->value << std::endl;
std::cout << "Letter: " << objects[1].getPtr()->letter;
return 0;
}
In this code, the output I should receive is
Value: 1
Letter: a
However I am receiving this
Value: 1
Letter
Also, if I were to declare letter before value (look at the comment in code), then the output would say
Value: 0
Letter: ☺
I'm not sure why the order I declare them in would affect anything, or why I'm getting a smiley face instead of a. Any help is appreciated, thank you!
The problem lies here:
ClassA(ClassB n) {
ptr = &n;
}
ClassB is a temporary variable that gets destructed at the end of the function. The pointer becomes invalid and the program goes nuts.
A simple and safe way to go about this, is to use an std::unique_ptr and pass parameters. unique_ptr will automatically delete ClassB when ClassA is deleted:
private:
std::unique_ptr<ClassB> ptr;
public:
ClassA(char t, int v) {
ptr = std::make_unique<ClassB>(t, v);
}
There's also just keeping a value instead of a pointer.
This question already has answers here:
How to use a member variable as a default argument in C++?
(4 answers)
Closed 1 year ago.
I tried to set a default parameter to a member variable, it gave me this bug.
[cquery] invalid use of non-static data member 'num'
code
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Despite it being quite obvious what this would mean, you just can’t. The usual workaround is to provide an overload that (implicitly) uses this to get the member value.
In order to set a default value for a function parameter to a class member, the member must be static.
Citing the documentation,
Non-static class members are not allowed in default arguments
However, given the context of your code sample I doubt this is what you want to do (as every instance of Test class will point to the same val. Citing the docs:
Static members of a class are not associated with the objects of the class: they are independent variables
If you make val static in your example, and have multiple instances of Test in use by your code, you can (and very likely will) have some unexpected behavior. Consider:
#include <iostream>
class Test{
private:
static int val;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
void set_val(int num) {
val = num;
}
}
int Test::val = 0;
int main(){
Test test1;
test1.set_val(1);
Test test2;
test2.set_val(2);
test1.print_num(); // results in "2"
return 0;
}
A better alternative would be to pass a pointer to your function like this:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int* numptr = nullptr){
int num = (numptr ? *numptr : val);
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Or, as described by Davis Herring, use an overload:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num){
std::cout << num << '\n';
}
void print_num() {
return print_num(val); // return is irrelevant here, but my preferred coding style
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Edited to reflect the comment and example.
Your function definition doesn't actually know what val is because it doesn't actually live inside of your class. The compiler is actually making a function that contains your class as a parameter and abstracts away all of that. You'll want to set num to val within the function body.
I wrote 2 contructors in my program with 2 different variables . However when calling them in main() I get an error saying :
main.cpp:23:11: error: no match for call to '(Basis) (const char [5])'
a("test");
This is my program :
#include <iostream>
using namespace std;
enum Test{Mo,Di};
class Basis
{
public:
Basis(std::string str) { cout << str; }
Basis(Test a)
{
cout << a;
}
};
int main()
{
Basis a(Di);
a("test"); //Error here
return 0;
}
Shouldn't this be working ? I'm assigning for each constructor its own variable .
The line where you have //Error here is not calling a constructor (since a is already instantiated).
Maybe you want something like this to create a second instance of Basis (thus calling the constructor you're wanting):
int main()
{
Basis a(Di);
Basis b("test"); //calls std::string constructor here
return 0;
}
The class Basis and its overloaded constructors are fine. The error is that
the code tries to call the parentheses operator method of the class.
And as there is no such method it thus provides the error you had documented.
Using parentheses to construct an object only works when you are first declaring it.
You can't reconstruct the object the variable is holding, however you can set the variable to a new object of that class. Like Elijay had stated.
a = Basis("test"); // Sets the variable
Well I guess this here answers my question . Dunno why no one mentioned it .
Just had to add a void operator to my public class
#include <iostream>
using namespace std;
enum Test{Mo,Di};
class Basis
{
public:
Basis(Test a)
{
cout << a;
}
void operator()(std::string str )
{
cout << str;
}
};
int main()
{
Basis a(Di);
a("test");
return 0;
}
This will print
1test
I apologize for posting such a basic question, but I cant find a decent answer as to why this doesn't work, and how to get it to work.
I have simplified my issue here:
#include <iostream>
using namespace std;
class A {
public:
int x;
};
void otherFunction() {
A A;
cout<<"X: "<<A.x<<endl;
}
int main(){
A A;
A.x = 5;
otherFunction();
return 0;
}
Do the class members become constant after constructing?
How do I expand the scope of changes done to the class?
Are structs limited in this way?
Thank you in advance for answers.
You are not getting the expected output because in otherFunction() you are creating a new object of type A for which you have not assigned a value before!
Read up on scope of a variable in C++ to learn more
Try running the code given below, you should get the output as 5.
#include <iostream>
using namespace std;
class A {
public:
int x;
};
void otherFunction(A a) {
cout << "X: " << a.x << endl;
}
int main(){
A a;
a.x = 5;
otherFunction(a);
return 0;
}
Alternatively you can do this, which is considered a good practice in OOP
class A{
private:
int x;
public:
void update(int newx){
x = newx;
}
int getX(){
return x;
}
};
int main(){
A a;
a.update(5);
cout << a.getX() << endl;
return 0;
}
It is doing what it is supposed to do.
You are creating a new object A inside the function otherFunction, this new object will be local to the function.
Print the the value of A.x after the call of function otherFunction in the main , you will see the the value of A.x has changed.
The variable A in main is not the same as the variable A in otherFunction, so they won't have the same value.
One way to give otherFunction access to the value of A in main is to pass it in as a parameter. For example:
void otherFunction(A p) {
cout<<"X: "<<p.x<<endl;
}
int main(){
A a;
a.x = 5;
otherFunction(a);
return 0;
}
I have changed the names of the variables to make it a bit more clear. a is in main, and a copy of a is passed into otherFunction. That copy is called p in otherFunction. Chnages that otherFunction makes to p will not cause any change to a.If you want to do that, you would need to pass by reference, which is probably a topic a bit further along than you are now.
The code:
int i;
struct st
{
int m;
}st_t[2];
void foo()
{
i = 4;
st_t[2] =
{
{10},{20}
}; // it's wrong !!!! but I don't know how to do.
}
int main()
{
foo();
cout<<i<<endl; // will output 4;
cout<<st_t[0].m<<endl; // this should output 10
cout<<st_t[1].m<<endl; // this should output 20
return 0;
}
Is it possible to define a struct array in a function? If it is, then how to do this?
Thanks in advance.
PS:
Sorry my English is not good. I am making a Tetris game, it have a Shape class, I declared a shape struct array in Shape.h, then I assign to the struct array in Shape constructor function in Shape.cpp. Is it right? or how to assign to the struct array so I can use it in another function?
You can initialize an array in the place where it's defined. I.e. either move the definition into the function, or move the initialization out of the function:
struct st
{
int m;
}
st_t[2] = {{10},{20}};
Instead of the direct assignment of values, you can initialize a temporary variable and copy this variable to your global variable:
Delete:
...
st_t[2] = {
{10},{20}
};
...
and add:
...
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t);
...
Addendum:
If it doesn't work for you, there might be another error in your code. From your example:
#include <iostream>
#include <memory.h>
using namespace std;
int i;
struct st { int m; } st_t[2];
void foo()
{
i = 4;
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t); // use: const_addr instead of &const_addr
}
int main()
{
foo();
cout << i << endl; // will output 4;
cout << st_t[0].m << endl; // this should output 10
cout << st_t[1].m << endl; // this should output 20
return 0;
}
all works fine as expected.
If you want to define an array in the function (as your question title and text implies), then add the type specifier st to the definition:
st st_t[2] =
{
{10},{20}
};
However, this will be a separate array to the global one, and so the output from main() won't match what your comments say should happen. If you actually want to assign to the global array, then:
st_t[0].m = 10;
st_t[1].m = 20;
or, in C++11, you can use similar syntax to your example if you replace the plain array with std::array:
std::array<st, 2> st_t;
void foo() {
// Note the extra braces - std::array is an aggregate containing an array
st_t =
{{
{10},{20}
}};
}
If you only want the variable at function scope then
void foo() {
struct {
int m;
} st_t = { {10}, {20} };
// do something
}