So I have 2 functions and 1 class.
with 1 function I want to Set value's of the integers stored in a class.
with the other function I want to use these value's again.
I'm using pointers as I thought this would be saved on Memory address's across the whole program.
#include <iostream>
using namespace std;
void Function1();
void Function2();
class TestClass
{
public:
TestClass();
~TestClass();
void SetValue(int localValue)
{
*value = localvalue;
}
int GetValue()const
{
return *value;
}
private:
*value;
};
TestClass::TestClass()
{
value = new int(0);
}
TestClass:
~TestClass()
{
delete value;
}
int main()
{
TestClass *tommy = new TestClass; //this didn't work,
//couldn't use SetValue or Getvalue in functions
Function1();
Function2();
return 0;
}
void Function1()
{
int randomvalue = 2;
TestClass *tommy = new TestClass; //because it didnt work in main, i've put it here
tommy->SetValue(randomvalue);
}
void Function2()
{
TestClass *tommy = new TestClass;
cout << tommy->GetValue();
<< endl; //this gave a error, so I put the above in again
//but this returns 0, so the value isn't changed
}
So, got a solution for me? I didn't got any compile errors, but the value isn't changed, probably because the destructor is called after Function1 has been completed. so how do I do it?
You need to pass your tommy from main() to each of your functions, not create a new one in each time, otherwise you're just losing the new Testclass objects you're creating in your functions, and actually here getting memory leaks because you use new.
Something like:
void Function1(TestClass * tommy) {
int randomvalue =2;
tommy->SetValue(randomvalue);
}
and then in main():
int main() {
TestClass *tommy = new TestClass;
Function1(tommy);
std::cout << tommy->GetValue() << std::endl; // Outputs 2
delete tommy;
return 0;
}
This is an odd use case, though - this would be the kind of thing you'd expect member functions to do. This would be better:
int main() {
TestClass *tommy = new TestClass;
tommy->SetValue(2);
std::cout << tommy->GetValue() << std::endl; // Outputs 2
delete tommy;
return 0;
}
without the need for Function1() and Function2(). Either way, you're going to have to fix:
private:
*value;
in your class, as someone else pointed out.
you are not passing your TestClass to either function so they functions can't see the tommy object you made. Then in each function you create a new local variable that just happens to have the same name as your local variable in main... They are all independent objects
Every time you write new TestClass, you are quite literally creating a new instance of a TestClass object. The new instance is not related to any existing instances in any way, except for being of the same type. To make the single instance of TestClass be "the one" being used by your functions, you need to pass it in as an argument to those functions.
Also -- Don't use pointers unless it is absolutely necessary.
Here's a cleaned up example of your code that accomplishes what it appears you were trying.
class TestClass
{
int value;
public:
TestClass() : value(0)
{}
int GetValue() const { return value; }
void SetValue(int x) { value = x; }
};
// takes a "reference", works somewhat like a pointer but with
// some additional safety guarantees (most likely will not be null)
// This will modify the original passed in TestClass instance.
void SetRandomValue(TestClass& tc)
{
int random = 2; // not really random...
tc.SetValue(random);
}
// take a const reference, similar to above comment, but a const
// reference cannot be modified in this scope
void Print(const TestClass& tc)
{
std::cout << tc.GetValue() << "\n";
}
int main()
{
// create a TestClass instance with automatic storage duration
// no need to use a pointer, or dynamic allocation
TestClass tc;
// Modify the instance (using reference)
SetRandomValue(tc);
// print the instance (using const reference)
Print(tc);
return 0;
}
Related
So I have a bunch of objects (subclasses of a parent class) with various functions each having different names, I might not have the resources to run all of the functions for each object so I want to have them in a priority list to run over time.
The code bellow is I believe forbidden by c++.
I get "C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function"
class A;
class Token;
list<Token> tokenList;
class Token{
public:
A* a; //Could be A or a child of A
int* function;
};
class A {
public:
A() {
Token token = Token();
token.a = this;
token.function = &A::hello;
tokenList.push_back(token);
}
int hello(){
cout << "hello" << endl;
return 0;
}
};
The code bellow should work but doesn't look elegant and also doesn't support subclasses having multiple functions they could pass to the list, is there a better way to do this I am missing?
class A;
list<A*> aList;
class A {
public:
virtual int funct();
};
class B : public A{
public:
virtual int funct(){
hello();
return 0;
}
int hello(){
cout << "hello" << endl;
return 0;
}
};
int main(){
//remove objects from list and run their functions in a loop until list is empty or max number of functions were run
Thanks Ted
Solution: Using the first example as mentioned I changed int* function; to int (A::*function)();. Then I can run the function with something like this
A tmp = A();
Token token = *tokenList.begin();
A *a = token.a;
(a->*token.function)();
}
The problem is that in your code int* function; is a pointer to an integer and not a pointer to a function.
If you would define it as int (*function)(); you could easily do what you want. But it would still not work with member functions.
So you need to define it as a pointer to a member function: int (A::*function)();
Here an example to make it work:
class Token{
public:
A* a; //Could be A or a child of A
int (A::*function)(); // pointer to member function with no arg, returning int
};
class A {
public:
A() {
Token token = Token();
token.a = this;
token.function = &A::hello; // Use the address of member function
tokenList.push_back(token);
}
int hello(){
cout << "hello (" << this <<")"<< endl; // added the address of a to see for which object
return 0;
}
};
int main() {
A a;
A b;
for (auto& token : tokenList )
(token.a->*token.function)(); // invoke the member function on the object pointer
}
Online demo
I didn't notice that your tokenList was a global variable. This is rather risky, as everything you create an A (including a temporary one), the tokenList will be updated. When you'll execute it, you'll therefore risk of having dangling pointers, i.e. pointing to an A instance that has already destroyed.
I'm coming from C# to C++ and when I try to construct tests, copy constructors are making it hard for me to mock the usual way I am accustomed to.
#include <iostream>
using namespace std;
class DB {
public:
virtual int getValue() { return 42; }
DB(const DB& source) { }
DB() { }
};
class DB_Mock: public DB {
public:
virtual int getValue() { return 999; }
};
class A {
public:
A(DB db) {
m_db = db;
}
void doIt() {
cout << "Result:" << m_db.getValue() << endl;
}
private:
DB m_db;
};
int main() {
/* prints 42 as expected */
DB db;
A a(db);
a.doIt();
/* prints 42, expected 999 */
DB_Mock db_mock;
A a2(db_mock);
a2.doIt();
return 0;
}
How do you approach problems like this?
m_db is not a reference or pointer, c++ polymorphism is work with only base class pointer or reference.
A(DB db) {
m_db = db; // m_db just sliced copy of base part of db.
}
Change this to reference like
class A
{
public:
explicit A(DB &db) : m_db(db) // it is initializing not copy
{
}
void doIt()
{
std::cout << "Result:" << m_db.getValue() << std::endl;
}
private:
DB &m_db; // Now m_db is reference
};
Compile and Run Here
Above will work But, You can not change reference value if you want to change use smart pointer[Recommended].
Reference :
Constructors and member initializer lists
Smart pointer
override
See virtual table to understand v_ptr
Edit:
As Pete Becker said be aware of lifetimes, if you pass local variable reference like
A make()
{
DB db;
A a(db);
return a;
}
int main()
{
const A &a = make();
// Wrong db is destroyed (dangling reference).
a.doIt(); // assume doIt(), getValue() are declared as const
return 0;
}
Above code is Wrong (undefined behaviour), So i Recommend to use smart pointer(Heap storage) to avoid this problems.
Thanks.
I am new to the std::function and trying to implement a callback function. In the following code "Callback_t" contains a function that holds a vector of function to be called. Class "other" is a nested class inside "SomeClass". An object of "SomeClass" contains an array of nested class object "b". The "other" class constructor assigns a function pointer to "fptr". I push this function in to the vector of callback class "Callback_t". When I run this code, I get the segmentation fault when the first function in the vector is invoked. I am not able to figure out what is wrong with the statement
this->loc_ptr->set_of_cb.push_back(this->b[i].fptr);
However if I replace it with
this->loc_ptr->set_of_cb.push_back(std::bind(&other::func, &(this->b[i])))
the code works perfectly. I need help to understand what's wrong with the original statement.
#include <functional>
#include <iostream>
#include <vector>
typedef std::function<void(void)> func_type;
class Callback_t {
public:
std::vector<func_type> set_of_cb;
void myCallback()
{
for (int i = 0; i < set_of_cb.size(); i ++){
set_of_cb[i]();
}
}
};
class SomeClass;
class SomeClass {
private:
Callback_t *loc_ptr;
int a[10];
class other{
public:
int id;
SomeClass *loc;
func_type fptr;
other(){};
other(SomeClass *loc, int id){
this->id = id;
this->loc =loc;
fptr = std::bind(&other::func,this);
}
void func(void){
this->loc->a[id] = loc->a[id] * id;
return;
}
};
public:
other *b;
//other b[10];
SomeClass(Callback_t *a = nullptr){
this->loc_ptr = a;
this->b = new other[10];
for(int i =0; i <10;i++){
this->a[i] = i;
this->b[i] = other(this, i);
this->loc_ptr->set_of_cb.push_back(this->b[i].fptr);
}
}
void read(void){
for(int i =0; i <10;i++){
std::cout<<a[i]<<std::endl;
}
}
};
int main()
{
Callback_t *tmp;
tmp = new Callback_t;
SomeClass tmp1(tmp);
tmp1.read();
tmp->myCallback();
tmp1.read();
delete tmp;
}
other(SomeClass *loc, int id){
this->id = id;
this->loc =loc;
fptr = std::bind(&other::func,this);
}
The constructor binds fptr to this, which is the constructed object. Now, pay careful attention:
this->b[i] = other(this, i);
This performs the following sequence of events. There are quite a few things happening here, that are crucial to this mystery:
A temporary other object gets constructed, and its constructor does what it does. Note that the object is temporary, so its constructor ends up binding its fptr to a temporary object! You're beginning to see the problem, but let's close the loop, anyway:
The object gets assigned to this->b[i]. This is effectively a copy.
The original temporary objects gets destroyed.
The end result is that b[i]'s bound function ends up getting bound to a temporary object that is now destroyed. This results in undefined behavior and your crash.
And with your working alternative:
this->loc_ptr->set_of_cb.push_back(std::bind(&other::func, &(this->b[i])))
You are binding the std::function to a valid instance of the object, in b[i].
That's it.
The other answer explains what is going wrong in your code. What is left to do is to show case a more canonical example of achieving what you go for (with a little help from lambda functions). Of course, std::bind() also works, but it is pre C++11 and I think nowadays most would rather do it as I do in my code below.
#include <iostream>
#include <functional>
#include <vector>
class Foo {
public:
void FooFun() {
std::cout << "Foo::FooFun() called" << std::endl;
}
};
class Bar {
public:
void BarFun() {
std::cout << "Bar::BarFun() called" << std::endl;
}
};
using CallbackFun_t = std::function<void()>;
using Callbacks_t = std::vector<CallbackFun_t>;
int main(int argc, const char * argv[]) {
Foo foo{};
Bar bar{};
Callbacks_t callbacks
{ [&foo]{ foo.FooFun();}
, [&bar]{ bar.BarFun();}
};
for( auto& cb : callbacks ) {
cb();
}
return 0;
}
Why does the following code print 0, but if you comment out "std::string my_string" it prints 1?
#include <stdio.h>
#include <iostream>
class A {
public:
virtual int foo() {
return 0;
}
private:
std::string my_string;
};
class B : public A {
public:
int foo() {
return 1;
}
};
int main()
{
A* a;
if (true) {
B b;
a = &b;
}
std::cout << a->foo() << std::endl;
return 0;
}
I also understand that changing std::string to std:string* also causes the code to print 1, as does removing the if-statement, though I don't understand why any of that is true.
EDIT: This seems to be due to a dangling pointer. Then what's the standard pattern in C++ to do something like this in Java:
Animal animal;
boolean isDog = false;
// get user input to set isDog
if (isDog) {
animal = new Dog();
} else {
animal = new Cat();
}
animal.makeNoise(); // Should make a Dog/Cat noise depending on value of isDog.
Problem
The program has Undefined Behaviour. b is only in scope inside the body of the if. You can't count on logical results when accessing a dangling pointer.
int main()
{
A* a;
if (true) {
B b; // b is scoped by the body of the if.
a = &b;
} // b's dead, Jim.
std::cout << a->foo() << std::endl; // a points to the dead b, an invalid object
return 0;
}
TL;DR Solution
int main()
{
std::unique_ptr<A> a; // All hail the smart pointer overlords!
if (true) {
a = std::make_unique<B>();
}
std::cout << a->foo() << std::endl;
return 0;
} // a is destroyed here and takes the B with it.
Explanation
You can point a at an object with a dynamic lifetime
int main()
{
A* a;
if (true) {
a = new B; // dynamic allocation
} // b's dead, Jim.
std::cout << a->foo() << std::endl;
delete a; // DaANGER! DANGER!
return 0;
}
Unfortunately delete a; is also undefined behaviour because A has a non-virtual destructor. Without a virtual destructor the object pointed at by a will be destroyed as an A, not as a B.
The fix for that is to give A a virtual destructor to allow it to destroy the correct instance.
class A {
public:
virtual ~A() = default;
virtual int foo() {
return 0;
}
private:
std::string my_string;
};
There is no need to modify B because once a function is declared virtual, it stays virtual for its children. Keep an eye out for final.
But it's best to avoid raw dynamic allocations, so there is one more improvement we can make: Use Smart pointers.
And that brings us back to the solution.
Documentation for std::unique_ptr
Documentation for std::make_unique
I have an std::unordered_map which stores an integer with an object. Here's some code for you to understand:
#include <iostream>
#include <unordered_map>
#include <cstdlib>
using namespace std;
class Foo
{
public:
Foo()
{
cout << "Foo created!" << endl;
}
~Foo()
{
}
};
typedef std::unordered_map<int, Foo*> FooMap;
FooMap fm;
int allocateID()
{
cout << "Allocating ID" << endl;
return rand() % 100;
}
void add()
{
fm.emplace(allocateID(), new Foo());
}
int main()
{
srand(time(NULL));
add();
return 0;
}
Output:
Foo created!
Allocating ID
The problem here is that the object Foo is created before an ID is allocated! I tried adding a mutex lock on allocateID; it didn't work because allocateID() runs AFTER the object is created.
How can I modify this program such that Foo is created AFTER the ID is allocated?
EDIT:
I've played around with the code and used a solution herein to demonstrate:
void add(int id, Foo *f)
{
auto iden = id;
auto foo = f;
fm[iden] = foo;
}
void add(Foo *f, int id)
{
auto iden = id;
auto foo = f;
fm[iden] = foo;
}
void add()
{
int id = allocateID();
fm[id] = new Foo();
}
In the first add() function, the output remains the same. This doesn't solve the problem.
In the second add() function, the output is different, instead producing:
Allocating ID
Foo created!
And in the third function, it has been modified with one of the solutions: this function also produces the desired output. The problem with the third function is that it's highly unlikely there would be an empty add() function realistically. The only culpable way of solving this issue is to pass the object first AND THEN the id. This is probably because the arguments are read from right to left, regardless of the entry requirements because they are created after the arguments are read anyway.
You can't rely on order of evaluation of function arguments. Try this:
void add()
{
int temp = allocateID();
fm.emplace(temp, new Foo());
}
Unless you are absolutely sure how the compiler will interpret your code, you don't want to rely on it and let it tell you what you wanted to do. Since you are having problems you should force the compiler to create the id first as such:
void add()
{
int id = allocateID();
fm[id] = new Foo();
}
This will fix your problems.