I got stuck with pointer to const QList of pointers to Foo. I pass pointer to myListOfFoo from Bar object to Qux. I use pointer to const to prevent making any changes outside Bar class. The problem is that I'm still able to modify ID_ executing setID in Qux::test().
#include <QtCore/QCoreApplication>
#include <QList>
#include <iostream>
using namespace std;
class Foo
{
private:
int ID_;
public:
Foo(){ID_ = -1; };
void setID(int ID) {ID_ = ID; };
int getID() const {return ID_; };
void setID(int ID) const {cout << "no change" << endl; };
};
class Bar
{
private:
QList<Foo*> *myListOfFoo_;
public:
Bar();
QList<Foo*> const * getMyListOfFoo() {return myListOfFoo_;};
};
Bar::Bar()
{
this->myListOfFoo_ = new QList<Foo*>;
this->myListOfFoo_->append(new Foo);
}
class Qux
{
private:
Bar *myBar_;
QList<Foo*> const* listOfFoo;
public:
Qux() {myBar_ = new Bar;};
void test();
};
void Qux::test()
{
this->listOfFoo = this->myBar_->getMyListOfFoo();
cout << this->listOfFoo->last()->getID() << endl;
this->listOfFoo->last()->setID(100); // **<---- MY PROBLEM**
cout << this->listOfFoo->last()->getID() << endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Qux myQux;
myQux.test();
return a.exec();
}
Result of above code is:
-1
100
and what I'm trying to achieve is:
-1
no change
-1
There is no such problem when I use QList<Foo> instead of QList<Foo*> but I need to use QList<Foo*> in my code.
Thanks for help.
should be:
QList<const Foo *>* listOfFoo;
You could use a QList<Foo const *> const * which means you are not allowed to modify the list or the content of the list. The problem is that there is no easy way to retrieve that list from a QList<Foo*>, so you need to add it in your Bar class.
If you really have to return pointer, cast it to QList containing pointers to constant elements:
QList<const Foo*> const* getMyListOfFoo()
{return reinterpret_cast<QList<const Foo*> *>(myListOfFoo_);};
In Qux listOfFoo should contain pointers to constant elements too:
QList<const Foo*> const* listOfFoo;
Related
Is there a way to use templates to create a standard constructor of class in your main?
If I have a class:
myclass.h
class myClass
{
private:
float a;
public:
myClass(float _a) {a = _a;}
float getA(){return a;}
~myClass() {}
};
Is there a way to template this in your main like so:
main.cpp
#include "myclass.h"
typedef myClass<5.0> Dummy
int main(int argc, char const *argv[])
{
// EDIT: removed the following typo
// Dummy dummy();
Dummy dummy;
std::cout << dummy.getA() << std::endl;
return 0;
}
Which should output:
> 5.0000000
So that one may define in the main a standard way to construct the instances.
C++17 and Below
Unfortunately C++ does not allow you to use floating point types as non-type template parameters yet. That said, you can fake it by accepting a numerator and denominator as integers and then doing that "math" in the class to get a floating point value. That would look like
template<size_t numerator, size_t denominator = 1> // use a default value so you don't have to specify the denominator for whole values
class myClass
{
private:
float a;
public:
myClass(float _a = static_cast<float>(numerator) / denominator) : a(_a) {}
float getA(){return a;}
~myClass() {}
};
typedef myClass<5> Dummy;
int main(int argc, char const *argv[])
{
Dummy dummy; // notice this isn't Dummy dummy();. That makes a function, not a variable
std::cout << dummy.getA() << std::endl;
return 0;
}
You could also add a default value to numerator if you want to so that you could do
// Pre C++17
myClass<> foo;
//C++17 and later
myClass foo;
C++20
Now that we can use floating point types1 the code can be simplified to:
template<float default_value = 0.0f>
class myClass
{
private:
float a;
public:
myClass(float _a = default_value) : a(_a) {}
float getA(){return a;}
~myClass() {}
};
typedef myClass<5.0f> Dummy;
int main(int argc, char const *argv[])
{
Dummy dummy;
std::cout << dummy.getA() << std::endl;
return 0;
}
1: no compilers actually support this yet, but it is allowed per the standard
Building onto #pptaszni's answer, you could create a "factory factory function":
auto makeMyClassFactory(float value) {
return [=] {
return myClass{value};
};
}
auto const Dummy = makeMyClassFactory(5.0f);
int main(int argc, char const *argv[])
{
auto dummy = Dummy();
std::cout << dummy.getA() << std::endl;
return 0;
}
See it live on Wandbox
You are possibly better off just using a default instance which you make copies of whenever you need a new instance:
#include "myclass.h"
Dummy myClass(5.0);
int main(int argc, char const *argv[])
{
myClass dummy1 = Dummy;
std::cout << dummy1.getA() << std::endl;
myClass dummy2 = Dummy;
std::cout << dummy2.getA() << std::endl;
return 0;
}
Not really, but you can write a factory function (or class if it is more complicated) like this:
myClass createMyClassV5()
{
return myClass(5.0);
}
Unfortunately, you cannot make it a template, because float are not allowed to be template non-type parameters. You could do it with int though.
Let me preference that I mostly develop in C# and the C++ development which I have done did not fully leverage the C++ language. I am now trying to use the language as it was intended and I am pulling my hair out with const declarations in passed arguments. In the past I never used them or hacked my way into making them work with the STL.
My understanding that I would create the following function when I want to use o as readonly in the function:
void foo(const MyClass* o);
So here is my problem...code first:
#include <iostream>
#include <string>
using namespace std;
///////////////////////////////////////////////////////////
// Classes are defined in the one file for an easy post.
///////////////////////////////////////////////////////////
class ClassA {
private: // member variables
string m_name;
public: // constructors
ClassA(const string& name = "") : m_name{name} {}
virtual ~ClassA() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
};
class ClassB {
private: // member variables
string m_name;
ClassA m_child;
public: // constructors
ClassB(const string& name = "") : m_name{name} {}
virtual ~ClassB() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
ClassA* child() { return &m_child; }
void setChild(const ClassA* value) { m_child = *value; }
};
///////////////////////////////////////////////////////////
// Protoptypes are not used to save space for the post.
void doSomethingA(const ClassA* o) {
cout << "name = " << o->name() << endl << endl;
}
void doSomethingB(const ClassB* o) {
cout << "name = " << o->name() << endl << endl;
doSomethingA(o->child());
}
///////////////////////////////////////////////////////////
int main(int argc, char** argv) {
ClassA a { "My Class A" };
ClassB b { "My Class B" };
b.setChild(&a);
b.child()->setName("My New Name");
doSomethingB(&b);
return 0;
}
In main() the compiler (g++ version 4.7.2) balks in doSomethingB:
doSomethingA(o->child());
with error: passing 'const ClassB' as 'this' argument of 'ClassA* ClassB::child()' discards qualifiers [-fpermissive]
Now I am passing my classes to functions as pointers. I plan on always using pointers because I have a problem with the reference/pointer options. I'm choosing one, pointers, and sticking with it. So doSomethingA and doSomethingB I want that to be const to tell the programmer that their class is not being altered. But I only want one version of child() which I want to use sometimes as "read only" and other times allow the user to change the data within the child object (not the best method, I grant that, but there are some use cases where I need this). I even tried:
doSomethingA(const_cast<const ClassA*>(o->child()));
But that did not work.
In the past I removed the const declarations in the functions to make something like this work but now I want to use proper c++. Help please.
try
ClassA* child() const { return &m_child; }
or
const ClassA* child() const { return &m_child; }
to keep the const correctness
Also, you don't need to use pointers as long as you don't plan passing nullptr. So you can do the following:
void doSomethingB(const ClassB& o);
// in class ClassB
const ClassA& child() const { return m_child; }
ClassA& child() { return m_child; }
References still alow polymorphic stuff same way as pointers.
You're attempting to access a non-const function against a const object. You need to make the function const :
const ClassA* child() const { return &m_child; }
You can also provide a const and non-const version:
ClassA* child() { return &m_child; }
const ClassA* child() const { return &m_child; }
This way you can call non-const methods on ClassA when you have a non-const object.
I'm working with some legacy code and I need a StoreStrings class storing
some strings and able to return a MyString*.
I've tried with this:
typedef char MyString[64];
class StoreStrings{
public:
void store(MyString *aStr)
{
theVec.push_back(aStr);
}
const MyString* get(){return theVec.begin();}
private:
std::vector<MyString> theVec;
};
But I'm disappointed since it doesn't compile with this syntax.
StoreStrings myStore;
myStore.store("Hello");//cannot convert parameter 1 from 'char [6]' to 'char (*)[64]'
I've to instantiate one MyString before.
MyString myStr = "Hello";
myStore.store(&myStr);
How can I rewrite the StoreStrings class so to have myStore.store("Hello"); compiling?
Arrays cannot be used in STL containers as it requires the type to be copy constructible and assignable
You may try following, however std::string approach is best.
typedef char MyString[64];
struct X{
MyString s;
};
class StoreStrings{
public:
void store(MyString aStr)
{
X temp ;
for(int i=0;aStr[i];++i)
temp.s[i] =*(aStr+i);
theVec.push_back(temp);
}
// Here iterator is returned.
const std::vector<X>::iterator get(){return theVec.begin();}
private:
std::vector<X> theVec;
};
int main(){
StoreStrings myStore;
MyString m ="Hello";
myStore.store(m);
}
I would suggest something like that
Storestring.h
#pragma once
#include <vector>
class StoreStrings
{
public:
void store(const char* aStr)
{
pszStr = new char[64];
strcpy_s(pszStr,64,aStr);
theVec.push_back(pszStr);
};
~StoreStrings(void){
for(std::vector<char*>::iterator it = theVec.begin();it!=theVec.end();++it){
delete *it;
}
};
std::vector<char*>::iterator getBegin(){return theVec.begin();};
std::vector<char*>::iterator getEnd(){return theVec.end();};
private:
char* pszStr;
std::vector<char*> theVec;
};
main.cpp
#include "StoreStrings.h"
#include <iostream>
int main(void){
StoreStrings s;
s.store("a");
s.store("b");
s.store("c");
for(std::vector<char*>::iterator it = s.getBegin();it!=s.getEnd();++it){
std::cout << *it<<std::endl;
}
return 0;
};
I've always wondered is there a way to have a class member without using getters that can only be modified by it's class?
What I'm thinking of is something like this.
class A
{
public:
crazyconst int x;
void doStuff()
{
// Gettin' stuff done
x = someValue; // OK
}
};
int main(int argc, char** argv)
{
A a;
a.x = 4; // ERROR
}
So it's visible, but read-only for everyone beside its class.
Your class could have a public const reference to a private, non-const data member.
Edit: However, I should point out that doing this would prevent you from using the compiler-generated copy constructor and copy assignment operator.
The answer is no you can't do this without a getter of some sort. However, you can make the getter reusable and you can make the simple syntax of a field work (mostly), without parentheses.
(C++11 required)
template<typename Friend, typename FieldType>
class crazyconst
{
FieldType value;
friend Friend;
FieldType& operator=(const FieldType& newValue) { return value = newValue; }
public:
operator FieldType(void) const { return value; }
FieldType operator()(void) const { return value; }
};
class A
{
public:
crazyconst<A, int> x;
void doStuff()
{
// Gettin' stuff done
x = 5; // OK
}
};
int main(int argc, char** argv)
{
A a;
int b = a.x;
int c = a.x(); // also works
}
C++03 version: http://ideone.com/8T1Po
But beware, this will compile but not work as expected:
const int& the_x = a.x;
a.doStuff();
std::cout << the_x;
OTOH, this should be fine:
const auto& ref_x = a.x;
a.doStuff();
std::cout << ref_x;
This is the simplest I could work my problem down to, sorry about the length:
#include <vector>
#include <iostream>
class Bar
{
private:
std::vector<int> intVector_;
public:
Bar() {};
void addInt(int newInt)
{
intVector_.push_back(newInt);
std::cout << intVector_.size() << " ";
};
int getIntVectorSize() { return intVector_.size(); };
};
class Foo
{
private:
Bar bar_;
public:
Foo() { bar_ = Bar(); };
Bar getBar() { return bar_; };
};
int main(char argc, char* argv[])
{
Foo foo = Foo();
foo.getBar().addInt(1);
std::cout << foo.getBar().getIntVectorSize() << " ";
foo.getBar().addInt(2);
std::cout << foo.getBar().getIntVectorSize() << " ";
foo.getBar().addInt(3);
std::cout << foo.getBar().getIntVectorSize() << " ";
}
My problem is that adding an int to the vector only seems to last for the duration of addInt(). My output for the size of the vector looks like this:
1 0 1 0 1 0
I'm rather new to C++ and all this reference/pointer business, so I am stumped as to how I can fix this, or if this is even possible. Thanks for any help!
It's because getBar() returns a Bar by value, which makes a copy of bar_ for every call of the function, and you are modifying the vector of the temporary.
You can avoid this by returning a reference:
class Foo
{
private:
Bar bar_;
public:
Foo() { bar_ = Bar(); }; // you prob. want to use an initialiser list btw.
Bar& getBar() { return bar_; };
// ^ notice the ampersand
};
This way, any modifications done on the return value of getBar are done on bar_ and not a temporary copy that is destroyed at the end of the statement.