I have this class MyClass that, most often, is created by parsing a string. I cannot trust that this string is always correct and therefore I do not want to put the parsing in the constructor. Hence, I have created a static parsing function that returns true if the string is valid and false if it is invalid. See below:
class MyClass
{
private:
Type1 m_memberA;
Type2 m_memberB;
public:
MyClass(const Type1& parameterA, const Type2& parameterB)
: m_memberA(parameterA), m_memberB(paramterB)
static bool parse(const std::string& input, MyClass * result)
{
Type1 paramA;
Type2 paramB;
//Parse input and get values for paramA and paramB.
//Return false if the input is invalid.
MyClass temp(paramA, paramB)
*result = temp;
return true;
}
}
My intent was to use it as follows:
void myFunction(const std::string& input)
{
MyClass * myObject = NULL;
if(MyClass::parse(input, myObject))
{
//Use myObject for something
}
else
{
//Log invalid input string
}
}
Now, this crashes at run time. And I figured that is because I am trying to de-reference a NULL-pointer, which obviously doesn't work. How can I fix this?
You need to pass either a pointer-to-pointer to the function or a pointer reference and allocate with new:
static bool parse(const std::string& input, MyClass *& result)
{
// ......
result = new MyClass(paramA, paramB)
return true;
}
Related
The below class is meant to be a top-layer class which brings all the benefits of nlohman::json but offers additional functions.
#include <nlohmann/json.hpp>
class Other { /* ... */ };
class AbstractData : public nlohmann::json
{
public:
AbstractData (const nlohmann::json& json) : nlohmann::json(json) { }
Other createOther(const char* key) { /* create Other class using key */ }
std::string toString() { /* convert to string */ }
/* etc. */
};
But I ran into issues when using operator[]. By default we have
AbstractData a;
auto& val = a["some_key"]; // val is nlohman::json::value_type&
and thus val loses all the extra functions.
When we provide a class function operator[]
const AbstractData& AbstractData::operator[](const char* key) const
{
return nlohmann::json::operator[](key);
}
then
AbstractData a;
auto& val = a["some_key"]; // val is AbstractData&
works as expected. But in order to achieve this, the copy constructor AbstractData (const nlohmann::json& json) is called (which is very inefficient for large objects). And this defeats the purpose of returning a reference in the first place.
I've seen questions like this one Add a method to existing C++ class in other file but they didn't offer help with my specific problem.
Any advice?
I would drop inheritance and wrap de data completely.
Why? Because the moment you need a second AbstractData, you will have to hold and potentially copy the json value. If you wrap the json data instead of using inheritance, then you can act as a view over json data.
class AbstractData {
// view over json
nlohmann::json const* _json_ptr;
auto json() -> nlohmann::json const& {
return *_json_ptr;
}
public:
AbstractData(nlohmann::json const& json) : nlohmann::json(&json) {}
Other createOther(const char* key) {
/* create Other class using key */
}
std::string toString() {}
auto operator[](const char* key) const -> AbstractData {
return AbstractData{&(json()[key])};
}
};
As you can see you can safely return by value, since your class only holds a pointer to your value and is cheap to copy.
If you also want your class to be the owner, you can store the json as a const shared pointer:
class AbstractData {
using root_t = std::shared_ptr<nlohmann::json const>;
// owner of the json root.
root_t _root;
// view over json
nlohmann::json const* _json_ptr;
auto json() -> nlohmann::json const& {
return *_json_ptr;
}
AbstractData(nlohmann::json const& json, root_t root) :
_root(root), _json_ptr(&json) {}
public:
struct new_root_t {} static constexpr new_root{};
AbstractData(new_root_t, nlohmann::json json) :
_root{std::make_shared<nlohmann::json const>(std::move(json))}, _json_ptr{_root.get()} {}
auto operator[](const char* key) const -> AbstractData {
// always pass down the root, so someone will own it
return AbstractData{json()[key], _root};
}
};
Live example
As a side note, you had undefined behaviour:
// return by reference?
const AbstractData& AbstractData::operator[](const char* key) const {
// construct a new, local value
// the local value is destroyed then returned
return nlohmann::json::operator[](key);
}
I strongly suggest to return by value here.
I want to write a class (Class2) that uses another class (Class1).
Class1 requires 2 parameters (the 2nd parameter is always the same so no need to talk about it).
Class2 require 1 parameter, and I want to check this parameter if its valid before passing it to an object created from Class1
So my code looks like this :
class Class1
{
public:
Class1(const string & filename, some_other_parameters);
...
};
class Class2
{
Class1 C1;
public:
Class2(const string & filename) // I want to verify this filename before passing it to C1 object
};
Class2::Class2(const string & filename)
: C1(filename, some_other_parameters){
}
int main()
{
Class2 myClass("file.txt");
}
So is there a way to check the filename before passing it to C1 or should I do it in the main() ?
Just invoke a static function to do the validation, but otherwise forward it's argument:
class Class2
{
Class1 C1;
static const std::string& validate_filename(const std::string& filename);
public:
Class2(const string & filename)
};
const std::string& Class2::validate_filename(const std::string& filename)
{
if (filename.size() < 2)
throw std::runtime_error("filename too short");
return filename;
}
Class2::Class2(const string & filename)
: C1(validate_filename(filename), some_other_parameters){
}
Note that you can use a similar technique if you want to transform the argument. So you can convert from wide char to utf8 and force the path to be in a canonical format, ... and still have the member variable be const.
You should also consider which class should be responsible for the validation. If C1 has constraints on its arguments, then it should check them. If on the other hand it would be fine with any string, but C2 has constraints, then it must do the checking.
You can just used a pointer for Class1
#include "stdafx.h"
#include <string>
class Class1
{
public:
Class1(const std::string & filename, int a)
{
// ...
}
};
class Class2
{
Class1 * p_C1;
public:
Class2(const std::string & filename)
{
// ------------------------------------
// Check the file before p_C1 creation
// ------------------------------------
p_C1 = new Class1(filename, 1);
}
~Class2(void)
{
if (p_C1 != NULL) delete p_C1;
}
};
int main()
{
Class2 myClass("file.txt");
}
I'm doing this:
template<typename T> class var_accessor {
public:
std::set<std::shared_ptr<T>> varset;
std::map<std::string,std::shared_ptr<T>> vars_by_name;
std::map<uint32,std::shared_ptr<T>> vars_by_id;
std::shared_ptr<T> operator[](const uint32& index) { return vars_by_id[index]; }
std::shared_ptr<T> operator[](const std::string& index) { return vars_by_name[index]; }
bool is_in_set(std::shared_ptr<T> what) { auto it = varset.find(what); if (it == varset.end()) return false; return true; }
bool is_in_set(uint32 what) { auto it = vars_by_id.find(what); if (it == vars_by_id.end()) return false; return true; }
bool is_in_set(std::string& what) { auto it = vars_by_name.find(what); if (it == vars_by_name.end()) return false; return true; }
bool place(std::shared_ptr<T> what, const uint32 whatid, const std::string& whatstring) {
if (is_in_set(what)) return false;
varset.emplace(what);
vars_by_name.emplace(whatstring,what);
vars_by_id.emplace(whatid,what);
return true;
}
};
Then...
class whatever {
std::string name;
std::function<int32()> exec;
};
And:
class foo {
public:
var_accessor<whatever> stuff;
};
This works:
std::shared_ptr<whatever> thing(new whatever);
thing->name = "Anne";
thing->exec = []() { return 1; }
foo person;
person.stuff.emplace(thing, 1, thing->name);
Getting the name crashes it:
std::cout << person.stuff[1]->name;
But if I change the operator[]'s to return references, it works fine.
I don't want to be able to accidentally add new elements without adding to all 3 structures, so that's why I made
std::shared_ptr<T> operator[]
instead of
std::shared_ptr<T>& operator[]
Is there any way to prevent assignment by subscript but keep the subscript operator working?
To be clear I want to be able to keep doing
std::cout << person.stuff[4];
But NOT be able to do
std::shared_ptr<whatever> bob(new whatever);
bob->name = "bob";
person.stuff[2] = bob;
The error is a EXC_BAD_ACCESS inside the std::string class madness
Everything I read says simply "don't return references if you want to prevent assignment" but it also prevents using it for me.
Yes I know some things should be made private but I just want to get it working first.
Using Clang/LLVM in XCode 5.1
Thanks!
You should return a const reference. See this question
A const reference means the caller is not allowed to change the value, only look at it. So assignment will be a compile-time error. But using it will work (and be efficient).
I have an object, every member variable in this object has a name which I can acquire it by calling get_name() ,what I want to do is concatenate all the names of the member variables in alphabetical order, then do something. for example:
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
}
//skip the get_name(), set_name() and others
private:
string m_local_name;
T m_type_var;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
...
}
I have to hard-code like this:
object o;
string sign = o.m_base.get_name();
sign += o.m_team.get_name();
I need a function to do this instead of copying and pasting when the object varies. Anyone has an idea?
One way to do this in normal C++, provided all of the members belong to the same class or are derived from some base class will be to use variable number of arguments to a function. An example follows.
#include <stdarg.h>
string concatenateNames(int numMembers, ...)
{
string output;
va_list args;
va_start(args, numMembers);
for(int i = 0; i < numMembers; i++)
{
MemberClass *pMember = va_arg(args, MemberClass*);
output += pMember->get_name();
}
va_end(args);
return output;
}
class Object
{
public:
MemberClass x;
MemberClass y;
MemberClass z;
};
int main()
{
Object o;
string sign = concatenateNames(3, &o.x, &o.y, &o.z);
}
If the types of all the members are different, you can look into variadic templates of C++11x: http://en.wikipedia.org/wiki/Variadic_Templates, but I can't seem to find a way to do otherwise.
If variables which have name have a same type (or these types belongs one hierarchy) you can use map of these vars. Is not good way, but maybe it helps you
Example
class object
{
public:
object() //: m_team("team"), m_base("base")
{
this->vars["m_team"] = CXMLWrapper<string>("team");
//.....
}
public:
map<string, CXMLWrapper<string> > vars;
/*CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;*/
...
}
object o;
string sign;
for(auto& x : o.vars)//i cannot remember syntax of for of map
sign += x.get_name;
PS Sorry for my writing mistakes. English in not my native language.
One method is to have an external library of member names which the CXMLWrapper class updates:-
class BaseXMLWrapper
{
public:
void ListMembers (const char *parent)
{
// find "parent" in m_types
// if found, output members of vector
// else output "type not found"
}
protected:
void RegisterInstance (const char *parent, const char *member)
{
// find 'parent' in m_types
// if not found, create a new vector and add it to m_types
// find 'member' in parent vector
// if not found, add it
}
private:
static std::map <const std::string, std::vector <const std::string> >
m_types;
};
class CXMLWrapper <class T, const char *parent> : BaseXMLWrapper
{
public:
CXMLWrapper(const char* p_name) : m_local_name(p_name)
{
RegisterInstance (parent, p_name);
}
// you could override assignments, copy and move constructors to not call RegisterInstance
//skip the get_name() set_name()
private:
m_local_name;
}
class object
{
public:
object() : m_team("team"), m_base("base")
{
}
public:
CXMLWrapper<string, "object"> m_team;
CXMLWrapper<string, "object"> m_base;
...
};
This does add overhead to the construction of objects, but as it's only a constructor overhead it might not affect overall system performance much.
This looks like a "observe pattern", you just need to keep a single copy in object as a member variable "string name_;", and pass the name_s's reference into CXMLWrapper like this:
class CXMLWrapper<class T>
{
public:
CXMLWrapper(const string &name)
: local_name_(name)
{
}
//skip the get_name() set_name()
private:
const string &local_name_;
}
class object
{
public:
object()
: team_("team"),
base_("base"),
m_team(team_)
, m_base(base_)
{
}
public:
string team_;
string base_;
CXMLWrapper<string> m_team;
CXMLWrapper<string> m_base;
}
I have a class called Object which stores some data.
I would like to return it by reference using a function like this:
Object& return_Object();
Then, in my code, I would call it like this:
Object myObject = return_Object();
I have written code like this and it compiles. However, when I run the code, I consistently get a seg fault. What is the proper way to return a class object by reference?
You're probably returning an object that's on the stack. That is, return_Object() probably looks like this:
Object& return_Object()
{
Object object_to_return;
// ... do stuff ...
return object_to_return;
}
If this is what you're doing, you're out of luck - object_to_return has gone out of scope and been destructed at the end of return_Object, so myObject refers to a non-existent object. You either need to return by value, or return an Object declared in a wider scope or newed onto the heap.
You can only use
Object& return_Object();
if the object returned has a greater scope than the function. For example, you can use it if you have a class where it is encapsulated. If you create an object in your function, use pointers. If you want to modify an existing object, pass it as an argument.
class MyClass{
private:
Object myObj;
public:
Object& return_Object() {
return myObj;
}
Object* return_created_Object() {
return new Object();
}
bool modify_Object( Object& obj) {
// obj = myObj; return true; both possible
return obj.modifySomething() == true;
}
};
You can only return non-local objects by reference. The destructor may have invalidated some internal pointer, or whatever.
Don't be afraid of returning values -- it's fast!
I will show you some examples:
First example, do not return local scope object, for example:
const string &dontDoThis(const string &s)
{
string local = s;
return local;
}
You can't return local by reference, because local is destroyed at the end of the body of dontDoThis.
Second example, you can return by reference:
const string &shorterString(const string &s1, const string &s2)
{
return (s1.size() < s2.size()) ? s1 : s2;
}
Here, you can return by reference both s1 and s2 because they were defined before shorterString was called.
Third example:
char &get_val(string &str, string::size_type ix)
{
return str[ix];
}
usage code as below:
string s("123456");
cout << s << endl;
char &ch = get_val(s, 0);
ch = 'A';
cout << s << endl; // A23456
get_val can return elements of s by reference because s still exists after the call.
Fourth example
class Student
{
public:
string m_name;
int age;
string &getName();
};
string &Student::getName()
{
// you can return by reference
return m_name;
}
string& Test(Student &student)
{
// we can return `m_name` by reference here because `student` still exists after the call
return stu.m_name;
}
usage example:
Student student;
student.m_name = 'jack';
string name = student.getName();
// or
string name2 = Test(student);
Fifth example:
class String
{
private:
char *str_;
public:
String &operator=(const String &str);
};
String &String::operator=(const String &str)
{
if (this == &str)
{
return *this;
}
delete [] str_;
int length = strlen(str.str_);
str_ = new char[length + 1];
strcpy(str_, str.str_);
return *this;
}
You could then use the operator= above like this:
String a;
String b;
String c = b = a;
Well, it is maybe not a really beautiful solution in the code, but it is really beautiful in the interface of your function. And it is also very efficient. It is ideal if the second is more important for you (for example, you are developing a library).
The trick is this:
A line A a = b.make(); is internally converted to a constructor of A, i.e. as if you had written A a(b.make());.
Now b.make() should result a new class, with a callback function.
This whole thing can be fine handled only by classes, without any template.
Here is my minimal example. Check only the main(), as you can see it is simple. The internals aren't.
From the viewpoint of the speed: the size of a Factory::Mediator class is only 2 pointers, which is more that 1 but not more. And this is the only object in the whole thing which is transferred by value.
#include <stdio.h>
class Factory {
public:
class Mediator;
class Result {
public:
Result() {
printf ("Factory::Result::Result()\n");
};
Result(Mediator fm) {
printf ("Factory::Result::Result(Mediator)\n");
fm.call(this);
};
};
typedef void (*MakeMethod)(Factory* factory, Result* result);
class Mediator {
private:
Factory* factory;
MakeMethod makeMethod;
public:
Mediator(Factory* factory, MakeMethod makeMethod) {
printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n");
this->factory = factory;
this->makeMethod = makeMethod;
};
void call(Result* result) {
printf ("Factory::Mediator::call(Result*)\n");
(*makeMethod)(factory, result);
};
};
};
class A;
class B : private Factory {
private:
int v;
public:
B(int v) {
printf ("B::B()\n");
this->v = v;
};
int getV() const {
printf ("B::getV()\n");
return v;
};
static void makeCb(Factory* f, Factory::Result* a);
Factory::Mediator make() {
printf ("Factory::Mediator B::make()\n");
return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb);
};
};
class A : private Factory::Result {
friend class B;
private:
int v;
public:
A() {
printf ("A::A()\n");
v = 0;
};
A(Factory::Mediator fm) : Factory::Result(fm) {
printf ("A::A(Factory::Mediator)\n");
};
int getV() const {
printf ("A::getV()\n");
return v;
};
void setV(int v) {
printf ("A::setV(%i)\n", v);
this->v = v;
};
};
void B::makeCb(Factory* f, Factory::Result* r) {
printf ("B::makeCb(Factory*, Factory::Result*)\n");
B* b = static_cast<B*>(f);
A* a = static_cast<A*>(r);
a->setV(b->getV()+1);
};
int main(int argc, char **argv) {
B b(42);
A a = b.make();
printf ("a.v = %i\n", a.getV());
return 0;
}
It isn't really good practice to return an initiated object as it does go out of scope. There are rare instances that this is the desired option. It actually can be done if the class is a referencing counting smart pointer or some other smart pointer.
How does a reference-counting smart pointer's reference counting work?