I have defined a class
class Version
{
public:
Version(std::string versionStr)
{
//do something
}
}
I want to be able to use it as follow
void foo(Version v1) {//do somthing};
void main()
{
foo("test");
}
I would like that v1 becomes an object as if I have done:
void main()
{
Version v1("test");
foo(v1);
}
is that possible?
The code you have has too many levels of implicit construction. "string literal" is of type const char [] and not std::string. Only one level of implicit construction occurs automatically. Try adding a constructor that takes const char * instead:
class Version {
// ...
Version(const char *_vstr) : versionStr(_vstr) {}
// ...
}
Live demo.
Related
I have this code:
class myclass
{
std::string str;
public:
void setStr(std::string value)
{
str=value;
}
std::string getStr()
{
return str;
}
}
main()
{
myclass ms;
std::cout<<ms.getStr()<<std::endl;
}
when I compile and run this code, there is o error and in windows I am always getting str as "".
Is this always valid?
I need the above behavior in the fact that if user did not call set, str would be always a blank string.
should I initialize str in constructor as follow:
class myclass
{
std::string str;
public:
myclass():str(""){}
void setStr(std::string value)
{
str=value;
}
std::string getStr()
{
return str;
}
}
I want to make sure that behavior is the same on all platform and also make sure that code is as small and neat as possible.
Do I need to initialize std::string
No. std::string default constructor initialises a nice empty string for you.
I want to make sure that behavior is the same on all platform and also make sure that code is as small and neat as possible.
Remove clutter then:
struct myclass {
std::string str;
};
Fundamental types though, do not get initialised by default, you need to initialize them explicitly:
struct myclass {
std::string str;
int i = 1; // <--- initialize to 1.
};
You dont need to initialize a string member with an empty string, though it can help to do it anyhows. Consider:
struct foo {
std::string a;
std::string b;
foo() : a("foo") {}
};
Was it by accident or on purpose that b does not get a value in the constructor? I'd prefer
foo() : a("foo"), b() {}
because it makes the intend explicit for no price (not counting a few keystrokes).
How to store temporary state, needed for the initializer list, in the constructor (on the stack)?
For example, implementing this constructor …
// configabstraction.h
#include <istream>
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
int m_x;
int m_y;
int m_z;
};
… using a stateful helper class like this?
// mysillyparserdontworry.h
#include <json/reader.h> //jsoncpp
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { input >> m_parseTree; }
int intByName(const char* name) const { return m_parseTree[name].asInt(); }
private:
Json::Value m_parseTree;
};
My attempt:
// configabstraction.cpp
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: local_parserState(input) // init local variable first: Not possible!
, m_a(local_parserState.intByName("a"))
, m_b(local_parserState.intByName("b"))
, m_c(local_parserState.intByName("c"))
{
MySillyParserDontWorry local_parserState; // ...because it is local
}
With C++11 you could solve this with delegating constructors:
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
ConfigAbstraction(const MySillyParserDontWorry& parser);
int m_a;
int m_b;
int m_c;
};
ConfigAbstraction::ConfigAbstraction(const MySillyParserDontWorry& parser)
: m_a{parser.intByName("a")}
, m_b{parser.intByName("b")}
, m_c{parser.intByName("c")}
{
}
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: ConfigAbstraction{MySillyParserDontWorry{input}}
{
}
An alternative solution to your problem would be packing the three individual ints into a common data structure. This would allow you to initialise an object of that type with a private static helper function. Being able to initialise the object instead of assigning to it later also allows for it to be const (if that is required).
Here is an example with std::tuple. But you could also create your own helper struct or even std::array<int, 3>; the basic idea remains the same: have one member object instead of three.
#include <istream>
#include <tuple>
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { /* ... */ }
int intByName(const char* name) const { return /* ... */ 0; }
};
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
static std::tuple<int, int, int> parse(std::istream& input)
{
std::tuple<int, int, int> result;
MySillyParserDontWorry parser(input);
std::get<0>(result) = parser.intByName("a");
std::get<1>(result) = parser.intByName("b");
std::get<2>(result) = parser.intByName("c");
return result;
}
std::tuple<int, int, int> const m;
};
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m(parse(input))
{
}
Why not simply doing the assignments in the constructor's body then?
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m_a(0)
, m_b(0)
, m_c(0)
{
MySillyParserDontWorry local_parserState;
m_a = local_parserState.intByName("a");
m_b = local_parserState.intByName("b");
m_c = local_parserState.intByName("c");
}
Is there any specific requirement that hinders you doing that?
What an artificial limitation of C++!
It's not an artificial limitation. How should initialisation of local variables be done outside of their function's scope? It would just lead to a great confusion, where variables are actually initialised (naming conflicts aside).
You can not initialize local variables bedfore members. The reason for this is very simple (so that it is NOT an artificial limitation):
Members have to be initialized (constructed) before constructor body begins, because constructor body might access them - and they need to be initialized for this access. On the other hand, local variables do not exist before code enters constructor body (as for any other function).
Conclusion - initialization of local variables before members is impossible.
const fields in C++ must be initialized in the initialization list, this makes non trivial the computation of interdependent values from the constructor parameters.
What is(are) the best way(s) to translate, for example, this piece of java code into c++ ?
public class SomeObject {
private final String some_string;
private final int some_int;
public SomeObject(final String input_filename){
SomeReader reader(input_filename);
some_string = reader.getString();
some_int = reader.getInt();
reader.close();
}
}
I thought of encapsulating a sub-object in SomeObject, but this is just shifting the problem; or constructing the object using a static method:
class SomeObject {
private:
const std::string some_string;
const int some_int;
public:
static SomeObject unserialize(const char * input_filename){
SomeReader reader = new SomeReader(input_filename);
string str = reader.get_string();
int i = reader.get_int();
reader.close();
SomeObject obj(str, i);
return obj;
};
SomeObject(const std::string str, const int i) :
some_string(str),
some_int(i)
{};
}
Is there a better solution ?
Thank you.
This is a great application for C++11 constructor delegation:
class SomeObject {
private:
const std::string some_string;
const int some_int;
public:
// The "real" constructor for SomeObject
SomeObject(std::string str, const int i) :
some_string{std::move(str)},
some_int{i}
{}
// Deserialize from SomeReader (delegates to the primary constructor)
SomeObject(SomeReader& reader) :
SomeObject{reader.get_string(), reader.get_int()} {}
// Deserialize from SomeReader (accepts rvalues,
// delegates to the lvalue constructor)
SomeObject(SomeReader&& reader) :
SomeObject{reader} {}
// Deserialize from named file (delegates to the SomeReader&& constructor)
SomeObject(const char* input_filename) :
SomeObject{SomeReader{input_filename}} {}
};
You can use a delegating ctor and a lambda-function, like this:
SomeObject(const char* filename) : SomeObject([&]{
/* Do calculations here */
return std::make_tuple(...);
}()) {}
SomeObject(std::tuple<...>&& x) : /* ... */ {}
Still, a much better idea is probably a re-design to make use of all the things you can do in C++ and cannot do in Java.
I think you have the right approach.
I would recommend couple of minor changes.
This is not correct C++.
SomeReader reader = new SomeReader(input_filename);
Perhaps you meant:
SomeReader reader(input_filename);
You can change the lines:
SomeObject obj(str, i);
return obj;
to
return SomeObject(str, i);
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?