My class doesn't work propery - c++

I'm getting an error in my code I don't get at all.
Here is my code:
MyClass.h
#include "MyClass.h"
int i = 1;
MyClass::MyClass()
{
}
MyClass:~MyClass()
{
}
MyClass.cpp
#pragma once
class MyClass
{
public:
MyClass();
virtual ~MyClass();
int i;
protected:
private:
};
main.cpp
#include<iostream>
#include "MyClass.h"
using namespace std;
int main()
{
MyClass myObject = *new MyClass();
cout << myObject.i << endl;
cin.get();
}
I just get some random number. Any help here?

You are not initializing i in your class, your constructor should look something like this:
MyClass::MyClass() : i(1)
{}
It also looks like you have a few typos, this:
MyClass myObject = *new MyClass();
should be:
MyClass *myObject = new MyClass();
and this:
cout << myObject.i << endl;
should be:
cout << myObject->i << endl;
Although, as chris says the simpler option would be as follows:
MyClass myObject ;
cout << myObject.i << endl;

The i that you set to 1 is not a member of the class. It is a static variable outside of any class.

Once i belongs to you class, you need to initialize it inside its constructor
#include "MyClass.h"
// int i = 1; <-- not here
MyClass::MyClass()
{
i = 1; // here
}
and to initialize your object in main function just do something like that:
int main()
{
// MyClass myObject = *new MyClass(); <-- myObject is not a pointer
MyClass myObject;
cout << myObject.i << endl;
cin.get();
}

Couple things wrong: First, you're redeclaring i in MyClass.cpp, try assigning to it in the constructor instead:
//int i = 1;
MyClass::MyClass() : i(1)
{
}
Second, the way you're declaring your object in your main() is wrong too. Either you do:
int main()
{
MyClass* myObject = new MyClass();
cout << myObject->i << endl;
cin.get();
delete myObject;
}
if you want a pointer to a dynamically allocated object or just
int main()
{
MyClass myObject;
cout << myObject.i << endl;
cin.get();
}
if you want an object allocated on the stack.

Related

how to initialize a class object reference in C++ to simulate NRVO?

I meet a course programming problem, which asks me to initialize the A a using passing by reference (initialize the A a in the func). How can I call A's constructor by A's reference?
#include <iostream>
using namespace std;
class A
{
public:
int x;
A()
{
cout << "default constructor" << endl;
x = 1;
}
A(int x)
{
cout << "constructor with param = " << x << endl;
this->x = x;
}
~A() {
cout << "destructor" << endl;
}
void print() {
cout << x << endl;
}
};
void fun(A& a)
{
a.A::A(10); // error!
return;
}
int main()
{
A a;
fun(a);
a.print();
return EXIT_SUCCESS;
}
There is a background of this problem. The teacher want us to replicate the NRVO(named return value optimization) result.
#include <iostream>
using namespace std;
class A
{
public:
int x;
A()
{
cout << "default constructor" << endl;
x = 1;
}
A(int x)
{
cout << "constructor with param = " << x << endl;
this->x = x;
}
~A() {
cout << "destructor" << endl;
}
void print() {
cout << x << endl;
}
};
A fun() {
A a = A(10);
return a;
}
int main()
{
A a = fun();
return EXIT_SUCCESS;
}
default g++ compiler:
constructor with param = 10
destructor
if we close the NRVO:
g++ test.cpp -fno-elide-constructors
constructor with param = 10
destructor
destructor
destructor
destructor
The teacher want us to replicate the NRVO(named return value optimization) result by passing by reference.
The syntax a.A::A(10); is incorrect.
Constructor is used to create an object of a class, you cannot call it on an already existing object. Even a constructor cannot be explicitly called. It is implicitly called by the compiler.
From general-1.sentence-2:
Constructors do not have names.
Thus, you cannot call a constructor explicitly. The compiler will automatically call the constructor when an object of that class-type is created.
You can not, not like this.
A reference always points to an initialized object. So you already failed before you called the function. The "return" argument is already initialized. And you can't initialized an initialized value again, not legally.
You can cheat by calling
std::construct_at(&a, 10);
For it to really reflect NRVO you could have something like this:
void fun(A *a)
{
std::construct_at(a, 10);
}
union UninitializedA {
std::byte uninitialized[sizeof(A)];
A a;
};
int main()
{
UninitializedA u;
fun(&u.a);
u.a.print();
u.a.~A();
return EXIT_SUCCESS;
}

Confusion about move constructor, rvalue passed as func parameter, and unque_ptr

I have a question relevant to move semantics and unique pointer.
Suppose I want to use a manager class to handle a heap allocated integer, and
(1) I delete copy constructor of the manager class to make the handle unique.
(2) The demo function consume is used to takeover ownership of the manager.
I found the following 3 ways all compiled. I was wondering if they all achieve my goal. Are they roughly the same? Any subtle difference? Which is considered as recommended?
(I)
#include <iostream>
#include <memory>
using namespace std;
class intManager {
public:
int* p;
intManager() {
cout << "constructor\n";
p = new int;
}
~intManager() {
cout << "destructor\n";
delete p;
}
intManager(intManager &src) = delete;
intManager(intManager&& src) {
cout << "move constructor\n";
this->p = src.p;
src.p = nullptr;
}
};
void consume(intManager m) {
return;
}
int main() {
intManager m{};
consume(move(m));
return 0;
}
/*
The program prints:
-------------------
constructor
move constructor
destructor
destructor
*/
(II)
#include <iostream>
#include <memory>
using namespace std;
class intManager {
public:
int* p;
intManager() {
cout << "constructor\n";
p = new int;
}
intManager(intManager &src) = delete;
~intManager() {
cout << "destructor\n";
delete p;
}
};
void consume(intManager &&m) {
return;
}
int main() {
intManager m{};
consume(move(m));
return 0;
}
/*
The program prints:
-------------------
constructor
destructor
*/
(III)
#include <iostream>
#include <memory>
using namespace std;
class intManager {
public:
int* p;
intManager() {
cout << "constructor\n";
p = new int;
}
intManager(intManager& src) = delete;
~intManager() {
cout << "destructor\n";
delete p;
}
};
void consume(unique_ptr<intManager> m) {
return;
}
int main() {
unique_ptr<intManager> bar = make_unique<intManager>();
consume(std::move(bar));
return 0;
}
/*
The program prints:
-------------------
constructor
destructor
*/

Can i use C++ function pointers like a C#'s Action?

In C ++, I first encountered function pointers.
I tried to use this to make it similar to Action and Delegate in C #.
However, when declaring a function pointer, it is necessary to specify the type of the class in which the function exists.
ex) void (A :: * F) ();
Can I use a function pointer that can store a member function of any class?
In general, function pointers are used as shown in the code below.
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(A::*BF)();
};
int main()
{
A a;
B b;
b.BF = &A::AF;
(a.*b.BF)();
return 0;
}
I want to use it like the code below.
is this possible?
Or is there something else to replace the function pointer?
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(* BF)();
};
int main()
{
A a;
B b;
b.BF = a.AF;
return 0;
}
I solved the question through the answer.
Thanks!
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class C {
public:
void CF() { std::cout << "C::F" << std::endl; }
};
class B {
public:
B(){}
std::function<void()> BF;
};
int main() {
A a;
C c;
B b;
b.BF = std::bind(&A::AF, &a);
b.BF();
b.BF = std::bind(&C::CF, &c);
b.BF();
int i;
std::cin >> i;
return 0;
}
What you want to do is probably something like this. You can use std::function to hold a pointer to a member function bound to a specific instance.
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class B {
public:
B(const std::function<void()>& bf) : BF(bf) {}
std::function<void()> BF;
};
int main() {
A a;
B b1(std::bind(&A::AF, &a)); // using std::bind
B b2([&a] { a.AF(); }); // using a lambda
b1.BF();
b2.BF();
return 0;
}
Here's a C# style implementation of the accepted answer, It is memory efficient and flexible as you can construct and delegate at different points of execution which a C# developer might expect to do:
#include <iostream>
#include <functional>
using namespace std;
class A {
public:
void AF() { cout << "A::F" << endl; }
void BF() { cout << "B::F" << endl; }
};
class B {
public:
std::function<void()> Delegate;
};
int main() {
A a;
B b;
b.Delegate = std::bind(&A::AF, &a);
b.Delegate();
b.Delegate = [&a] { a.BF(); };
b.Delegate();
return 0;
}

C++: String parameter in base class deconstructs when the derived class deconstruction

I have a base class named A containing a string type parameter.
Class B is derived from A.
I define class C have parameter A* a, and
assign it to B.
In the main function, I cannot get the string value of the base class as it became blank when b deconstructs.
I want it to output:
"Hello!"
"Hello!"
end
But the output is:
"Hello!"
end
Here is my code:
class A {
public:
string str;
};
class B : public A {
public:
B(string _str) {
str = _str;
}
};
class C {
public:
A *a;
public:
void printOut() {
B b("Hello!");
a = &b;
cout << a->str << endl;
}
};
int main() {
C c;
c.printOut();
cout << c.a->str << endl;
cout << "end" << endl;
return 0;
}
How can I deal with it?
Correct, because B b("Hello!"); goes out of scope, c.a is now a dangling pointer that will cause undefined behaviour upon being dereferenced. If you want it to outlive the scope you could allocate it on the heap instead :
class A {
public:
string str;
};
class B : public A {
public:
B(string _str) {
str = _str;
}
};
class C {
public:
A *a;
public:
void printOut() {
B* b = new B("Hello!");
a = b;
cout << a->str << endl;
}
};
int main() {
C c;
c.printOut();
cout << c.a->str << endl;
cout << "end" << endl;
delete c.a;
return 0;
}
This gets messsy real fast though because you have to track the memory allocated yourself and call delete appropriately, consider redesigning or using smart pointers.
Why are you storing an A* ? You know that doesn't work, so stop doing it.
Make a copy of the A object, or a copy of the string it contains, and stop trying to do something silly.
class A {
public:
string str;
};
class B : public A {
public:
B(string _str) {
str = _str;
}
};
class C {
public:
string str;
public:
void printOut() {
B b("Hello!");
str = b.str;
cout << str << endl;
}
};
int main() {
C c;
c.printOut();
cout << c.str << endl;
cout << "end" << endl;
return 0;
}

C++ why is this destructor called and where does it come from

I'm learning about desctructors, copy and clone and therefor I wrote this code. Everything is clear to me but one line. It is the destructor in line 5 Destructor myClass1 0x28fec0. Where does it come from and why is it called?
Console output:
Constructor myClass1 0x28fe98
Constructor myClass2 0x28fe88
Constructor myClass3 0x28fe78
operator=
Destructor myClass1 0x28fec0
clone
Constructor clone 0x28fed0
operator=
Destructor clone 0x28fed0
Destructor myClass3 0x28fe78
Destructor myClass2 0x28fe88
Destructor myClass1 0x28fe98
main.cpp:
#include <iostream>
#include "MyClass.h"
int main(){
MyClass myClass1("myClass1"), myClass2("myClass2"), myClass3("myClass3");
myClass2 = myClass1;
myClass3 = myClass1.clone();
return 0;
}
MyClass.h:
#ifndef MYCLASS_H
#define MYCLASS_H
#include <iostream>
#include <string>
class MyClass{
private:
int *values;
int size;
int *copies;
std::string name;
public:
MyClass();
MyClass(std::string name);
~MyClass();
void operator=(MyClass myClass);
MyClass clone();
};
#endif
MyClass.cpp:
#include "MyClass.h"
MyClass::MyClass(){
std::cout << "Constructor" << this << std::endl;
name = "None";
size = 1;
values = new int[1];
values[0] = 0;
copies = new int;
*copies = 1;
count++;
}
MyClass::MyClass(std::string name){
std::cout << "Constructor " << name << " " << this << std::endl;
size = 1;
values = new int[1];
values[0] = 0;
copies = new int;
*copies = 1;
count++;
this->name = name;
}
MyClass::~MyClass(){
std::cout << "Destructor " << name << " " << this << std::endl;
if(*copies == 1){
delete [] values;
values = 0;
delete copies;
copies = 0;
}
count--;
}
void MyClass::operator=(MyClass myClass){
std::cout << "operator=" << std::endl;
if(*copies == 1){
delete copies;
copies = 0;
delete [] values;
values = 0;
}
size = myClass.size;
values = myClass.values;
copies = myClass.copies;
(*copies)++;
}
MyClass MyClass::clone(){
std::cout << "clone" << std::endl;
MyClass myClass("clone");
myClass.size = size;
delete [] myClass.values;
myClass.values = new int[size];
for(int i = 0; i < size; i++){
myClass.values[i] = values[i];
}
return myClass;
}
Because you're taking the argument to operator= as a copy.
So it creates a MyClass object inside operator=, which gets destroyed when operator= returns.
void MyClass::operator=(MyClass myClass) takes its argument by value. So, when you call
myClass2 = myClass1;
the copy constructor creates a copy of myClass1 into the MyClass argument of MyClass::operator=. When that function finishes, this copy is destroyed. To see this happening, put print statements in the copy constructor MyClass::MyClass(const MyClass&).
Also, quoting from cppreference, the canonical overload of the assignment operator for a type T is
T& T::operator=(T arg) { // copy/move constructor is called to construct arg
swap(arg); // resources exchanged between *this and arg
return *this;
} // destructor is called to release the resources formerly held by *this
This is the copy-and-swap idiom. Also note that the return type is T& and not void.
void operator=(MyClass myClass); should be MyClass& operator=(const MyClass& myClass); (standard). Else, you pass myClass by copy, meaning that a temporary object is created....and then destroyed.