I have a class that has a property named title implemented as a nested class, how can I call std::strings's methods on it ? (I am trying to make hidden encapsulation.)
#include <iostream>
class test {
public:
class {
private :
std::string value;
public:
operator const std::string & () {
return value;
}
void operator =(const std::string & source) { value = source;}
} title;
};
int main() {
test t;
t.title = "title"; // this works.
t.title.find("t"); // error here.
}
Related
I'd like to do something like:
class StrToHex {
public:
??? StrToHex(std::string a) {
return class_method1(a) + class_method2(a);
}
private:
std::string method1(std::string a);
std::string method2(std::string a);
}
int main() {
std::string var = StrToHex("FF1042");
}
I know that I may use StrToHex::MyFunc() or create class object, but is there any way to do without it?
In C++ a constructor cannot return a value. So you cannot specify a return type for a constructor. But there are other alternative ways to achieve the same. I have used a std::string cast operator here.
class StrToHex {
public:
StrToHex(std::string a) {
_data = method1(a) + method2(a);
};
operator std::string()
{
return _data;
};
private:
std::string method1(std::string a)
{
return std::string("Hi " + a);
};
std::string method2(std::string a)
{
return std::string(" again " + a);
};
std::string _data;
};
int main() {
std::string var = StrToHex("FF1042");
std::cout << var;
}
I hope it helps!.
I have a class named Demo and in that class I have overloaded the Text() method for setting and getting it's private variable called text.
#ifndef DEMO_H
#define DEMO_H
#include <string>
#include <iostream>
using namespace std;
class Demo {
string text;
public:
Demo() {};
Demo(string newText) : text(newText) {};
void Text(string updatedText);
string Text();
};
#endif // !DEMO_H
void Demo::Text(string updatedText) {
text = updatedText;
}
string Demo::Text() {
return text;
}
Then in another class, I have used the method in following way-
#include "Demo.h"
int main()
{
Demo d;
d.Text("test");
cout << d.Text() << endl;
return 0;
}
This works fine. However, I want to set the parameter of the method with "=" operator. So rather than
d.Text("test");
I want to do
d.Text = "test";
Is it possible to achieve in C++ and if so then how. I was thinking of operator overloading but I couldn't achieve the goal. Can anyone please suggest.
The closest you can get in c++ to express property like getter / setter functions similar as in c# is to provide class member functions like these:
class Demo {
string text;
public:
void Text(const string& updatedText) { text = updatedText; }
const string& Text() const { return text; }
};
That idiom is used a lot in the c++ standard library like here.
I want to do
d.Text = "test";
What you can do is
class Demo {
public:
string& Text() { return text; }
};
and
d.Text() = "test";
but that totally defeats the concept of encapsulation of data.
The right way to proceed is overloading the assignment '=' operator and use as below.
class Demo {
string text;
public:
Demo() {};
Demo(string newText) : text(newText) {};
**void operator =(const string& val) { text = val; }**
void Text(string updatedText);
string Text();
};
int main()
{
Demo d;
//d.Text("test");
d = "hello world";
cout << d.Text() << endl;
return 0;
}
You could define your Text property as an object T. T could then overload some common property operations ( haven't figured out how a common getter call like Object o; o.set(d.Text); would be implemented yet ) :
#include <iostream>
using namespace std;
class T {
string _text;
public:
void operator =(const string& t) { _text = t; }
friend ostream& operator<<(ostream& os, const T& obj)
{
cout << obj._text;
return os;
}
};
class Demo {
public:
T Text;
};
int main()
{
Demo d;
d.Text = "test";
cout << d.Text << endl;
}
I'm doing an assignment for class and I'm getting weird compile errors.
The errors are saying error: 'Noble' has not been declared and error: class 'Warrior' does not have any field named 'pBoss'.
I'm new to C++ so I really don't get what I'm doing wrong here - it seems like I declared both classes and all the member fields.
#include <vector>
#include <iostream>
#include <ostream>
using namespace std;
class Warrior {
public:
Warrior(string name, double str) : name(name), strength(str), pBoss(nullptr) {}
bool hire(Noble* noble) { }
bool fire(Noble* noble) { }
void lost() { }
void won(double damageRatio) { }
string getName() const { return name; }
double getStrength() const { return strength; }
Noble* getBoss() const { return pBoss; }
void display(ostream& os = cout) const { }
private:
string name;
double strength;
Noble* pBoss;
};
class Noble {
public:
Noble(string name) : name(name), alive(true) {}
bool hire(Warrior& war) { }
bool fire(Warrior& war) { }
bool battle(Noble& enemy) { }
void display(ostream& os = cout) const { }
private:
vector<Warrior*> army;
string name;
double strength;
bool alive;
void lost() { }
void won(double damage) { }
};
I took out the function descriptions so this won't be too long, but let me know if there is anything I didn't include and I'll update the post!
By the time you define Warrior, Noble is not yet defined. C++ works line by line. To fix this you could forward declare the classes.
// forward declaration
class Warrior;
class Noble;
class Warrior {
// ...
};
class Noble {
// ...
};
Warrior has no idea what a Noble is. You need to forward declare Noble. Place this before the Warrior declaration:
class Noble;
class Warrior { ...
Furthermore, you've misspelled pBoss in the Warrior constructor, change the constructor to:
Warrior(string name, double str) : name(name), strength(str), pBoss(nullptr) {}
Lastly you have an extra close brace floating around in Noble after the display declaration.
Looks like you may have an extra brace in your noble class:
class Noble {
public:
Noble(string name) : name(name), alive(true) {}
bool hire(Warrior& war) { }
bool fire(Warrior& war) { }
bool battle(Noble& enemy) { }
void display(ostream& os = cout) const { }
} // <-- out of place?
private:
vector<Warrior*> army;
string name;
double strength;
bool alive;
void lost() { }
void won(double damage) { }
};
Hi i am trying to create a simple ORM in c++ for a project. For this example assuming a simple class as
class userProfile: public BaseOrm
{
public:
string username;
string email;
};
Now base orm has a method save() and migrate(). What i want is when a person calls migrate() all the schema , in this case username and email are populated as db tables and on save they persist on database.
What i am having problem with is how do i get what all fields are defined in the class, like in this example username and email and also there types, string in this case. Any help would be appreciated.
I know there is no reflection in c++, so i don't actually care about the variable name but more on the number of variables and there types to map them with DB.
adding reflection to c++ is not insanely difficult but it does require a reasonably good knowledge of template type deduction and some careful planning.
In this working example I have made a start for you. This framework supports writing the members out to a "statement" class (modelling a database prepared statement).
Similar techniques can be used to build out the SQL generation for CRUD.
No doubt there are already libraries that do this for you...
#include <iostream>
#include <iomanip>
#include <string>
#include <tuple>
#include <utility>
using namespace std;
struct statement
{
void setString(int index, const std::string& value)
{
std::cout << "setting index " << index << " to value " << std::quoted(value) << std::endl;
}
};
struct BaseOrm
{
virtual void serialise(statement& stmt) const = 0;
};
template<class Class>
struct class_tag {
using type = Class;
};
template<const char* Name>
struct name_tag {
static constexpr const char* name() { return Name; }
};
namespace detail {
struct reflection_item_concept
{
virtual const std::string& name() const = 0;
virtual std::string to_archive_string(const void* object) const = 0;
virtual void from_archive_string(void* object, const std::string& as) const = 0;
};
template<class T>
std::string to_archive_string_impl(const T& val) {
return std::to_string(val);
}
const std::string& to_archive_string_impl(const std::string& s) {
return s;
}
template<class NameTag, class Class, class Type>
struct reflection_item : reflection_item_concept
{
reflection_item(Type Class::* mfp) : mfp(mfp) {}
static const class_tag<Class> class_info() { return {}; };
static const char* raw_name() { return NameTag::name(); };
// concept implementation
const std::string& name() const override {
static const std::string s = raw_name();
return s;
}
std::string to_archive_string(const void* object) const override
{
auto& val = (*reinterpret_cast<const Class*>(object)).*mfp;
return to_archive_string_impl(val);
}
void from_archive_string(void* item, const std::string& as) const override
{
// similar mechanism here
}
Type Class::* mfp;
};
}
template<class NameTag, class Class, class Type>
constexpr auto reflection_item(NameTag, Type Class::* mp)
{
return detail::reflection_item<NameTag, Class, Type> { mp };
}
struct class_reflection_concept
{
virtual void serialise(const void* object, statement& stmt) const = 0;
};
namespace detail {
template<class ClassTag, class...ReflectionItems>
struct reflection_impl : class_reflection_concept
{
reflection_impl(ReflectionItems...refs)
: _reflectors(std::make_tuple(refs...))
{}
template<std::size_t...Is>
void serialise_impl(std::index_sequence<Is...>, const void* object,
statement& stmt) const
{
using expand = int[];
void(expand{
0,
(stmt.setString(Is + 1, std::get<Is>(_reflectors).to_archive_string(object)),0)...
});
}
void serialise(const void* object, statement& stmt) const override
{
serialise_impl(std::make_index_sequence<sizeof...(ReflectionItems)>(),
object, stmt);
}
std::tuple<ReflectionItems...> _reflectors;
};
}
template<class ClassTag, class...ReflectionItems>
auto& make_reflection(ClassTag tag, ReflectionItems...items)
{
static const detail::reflection_impl<ClassTag, ReflectionItems...> _ { items... };
return _;
}
const char txt_username[] = "username";
const char txt_email[] = "email";
const char txt_x[] = "x";
class userProfile: public BaseOrm
{
public:
string username = "test username";
string email = "noone#nowhere.com";
int x = 10;
// implement serialisation
void serialise(statement& stmt) const override
{
reflection.serialise(this, stmt);
}
static const class_reflection_concept& reflection;
};
const class_reflection_concept& userProfile::reflection =
make_reflection(class_tag<userProfile>(),
reflection_item(name_tag<txt_username>(), &userProfile::username),
reflection_item(name_tag<txt_email>(), &userProfile::email),
reflection_item(name_tag<txt_x>(), &userProfile::x));
int main()
{
userProfile x;
statement stmt;
x.serialise(stmt);
}
expected results:
setting index 1 to value "test username"
setting index 2 to value "noone#nowhere.com"
setting index 3 to value "10"
What I understand is that you want a generic behaviour for classes which have a variable set of fields.
I suggest you to create a "field" interface which will be stored in your base class with a container (for example a map of [fieldName, fieldInterface]). You still have to implement a behaviour for each field's type, but then you can create any class derived from the base class which have a dynamic set of field.
Here is an example :
#include <iostream>
#include <map>
using namespace std;
//the "Field" interface
class IFieldOrm
{
public:
virtual ~IFieldOrm() {}
virtual void save() = 0;
virtual void migrate() = 0;
};
//your base class
class BaseOrm
{
public:
virtual ~BaseOrm();
virtual void save();
virtual void migrate();
protected:
map<string, IFieldOrm*> m_fields; //prefer a smart pointer if you don't want to mess with raw pointer
};
//base class implementation
void BaseOrm::save()
{
for(auto& f : m_fields)
f.second->save();
}
void BaseOrm::migrate()
{
for(auto& f : m_fields)
f.second->migrate();
}
//don't forget to free your "fields" pointers if you have raw pointers
BaseOrm::~BaseOrm()
{
for(auto& f : m_fields)
delete f.second;
}
//then implement your basic types
//(like string, int, ..., whatever type you want to store in your database)
class StringFieldOrm : public IFieldOrm
{
public:
StringFieldOrm(const string& value) : m_value(value) {}
virtual void save();
virtual void migrate();
private:
string m_value;
};
void StringFieldOrm::save()
{
cout << "Save value " << m_value << endl;
//save stuff...
}
void StringFieldOrm::migrate()
{
cout << "Migrate value " << m_value << endl;
//migrate stuff...
}
class IntFieldOrm : public IFieldOrm
{
public:
IntFieldOrm(int& value) : m_value(value) {}
virtual void save();
virtual void migrate();
private:
int m_value;
};
void IntFieldOrm::save()
{
cout << "Save value " << m_value << endl;
//save stuff...
}
void IntFieldOrm::migrate()
{
cout << "Migrate value " << m_value << endl;
//migrate stuff
}
//and finally implement your final class
//note that this object can be "dynamically extended" by inserting new fields,
//you may want to prevent that and I can think of a solution if you want to
class UserProfile: public BaseOrm
{
public:
UserProfile(const string& username, const string& email, int age);
};
UserProfile::UserProfile(const string& username, const string& email, int age)
{
m_fields["username"] = new StringFieldOrm(username);
m_fields["email"] = new StringFieldOrm(email);
m_fields["age"] = new IntFieldOrm(age);
}
int main(int argc, char* argv[])
{
UserProfile user = UserProfile("Batman", "bw#batmail.com", 30);
user.save();
return 0;
}
create a userProfile variable and access them:
userProfile user;
int main(){
std::cout << user.username;
std::cout << user.email ;
}
this is how you would access them, except for different reasons, not printing them to the screen.
I have 2 simple C++ headers implemented as in the following:
Attribute.h
#include <string>
using namespace std;
class IAttribute
{
virtual string getName(){};
};
class StringAttribute : public IAttribute
{
private:
string name = "";
string value = "";
public:
StringAttribute(string name, string value)
{
this->name = name;
this->value = value;
}
string getName()
{
return this->name;
}
string getStrValue()
{
return value;
}
void setValue(string value)
{
this->value = value;
}
};
tableRow.h
#include "attribute.h"
#include <vector>
using namespace std;
class TableRow
{
private:
vector<IAttribute *> attributeList;
int rowId;
public:
TableRow(int rowId)
{
this->rowId = rowId;
}
void addStrAttribute(string name, string value)
{
attributeList.push_back(new StringAttribute(name, value));
}
StringAttribute getStrAtt(string name)
{
for (int i = 0; i < (int)attributeList.size(); i++)
{
if (attributeList[i]->)//couldn't access the methods of StringAttributeImp
{
}
}
}
};
As in the comment of tableRow header above, I couldn't access the methods and properties of the Implementation class. What is wrong?
The getName function is private in the IAttribute class. So of course you're not able to access it.
You should change the getName function to public; or use friend class.