Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I would like to ask the proper location of typedef in C++.
Version1 : typedef outside class
typedef std::pair<std::string, int> StrIntPair;
typedef std::vector<StrIntPair> StrIntPairVec;
class MyData
{
public:
MyData(){};
~MyData(){};
private:
void addInfo(const StrIntPair &info)
{
infoVec.push_back(info);
}
StrIntPair info;
StrIntPairVec infoVec;
};
Version2 : typedef inside class public
class MyData
{
public:
MyData(){};
~MyData(){};
typedef std::pair<std::string, int> StrIntPair;
typedef std::vector<StrIntPair> StrIntPairVec;
private:
void addInfo(const StrIntPair &info)
{
infoVec.push_back(info);
}
StrIntPair info;
StrIntPairVec infoVec;
};
Version3 : typedef inside class private
class MyData
{
public:
MyData(){};
~MyData(){};
private:
typedef std::pair<std::string, int> StrIntPair;
typedef std::vector<StrIntPair> StrIntPairVec;
void addInfo(const StrIntPair &info)
{
infoVec.push_back(info);
}
StrIntPair info;
StrIntPairVec infoVec;
};
Which version is the best practice?
This depends on where you use the type alias. I'd advice you to
Put them outside of the class if you use them across classes and/or functions and the meaning of the alias is not exclusively related to the class.
Define them as public class type aliases if client code outside of the class needs to access them (e.g. to initialize the object or to store an aliased return value of a member function) but the alias is related to the class. The alias then becomes a part of the class interface.
Define them as private class type aliases when you use them exclusively inside the class, e.g. some utility data structure that is annoying to type out all the time when passing it across member functions.
The compiler will only enforce scopes of aliases that are too narrow (e.g. you use a type alias defined in the private section of your class outside of that class) and won't complain if you choose an unnecessarily permissive scope (e.g. you publicly declare the alias, but use it only in the class implementation). Hence, strive to choose the narrowest scope possible, which is in line with hiding implementation details.
As a side note, you might want to consider declaring your type aliases with using StrIntPair = std::pair<std::string, int>;, see Item 9 in Effective Modern C++. This has no influence on the above, though.
The question is about logical namespace of those names. With abstract naming like StrIntPair, StrIntPairVec and MyData there are no answers. Answers come when the things have meaning.
Lets take exactly same data structures but name them NickAndId, Friends and Player.
Now the question if to put NickAndId inside Player is about if it is specific to player. Can other entities like NonPlayerCharacter or Creature also have nickname and id expressed as same pair? Possibly. Then it should be outside.
Same question should be asked about Friends. Likely the NonPlayerCharacter and Creature can have nickname and id but do not have friends? Then it makes sense to put the type inside of Player as Player::Friends.
Finally, the types that are made private are meant only for usage by implementation details. That should be used when the name makes perfect sense in algorithms used inside of class but availability of those outside is unneeded or even worse, confusing. For example NonPlayerCharacter can react with some replicas to some states whose values are also internal to that NPC. Keeping that in sorted vector Reactions makes perfect sense inside of class. Access to ReplicaInState and Reactions from outside can be confusing.
Related
This question already has answers here:
When should you use a class vs a struct in C++? [duplicate]
(27 answers)
Closed 1 year ago.
I have basic knowledge of structures from C, and as far as I'm aware, classes and structs are not exactly the same, but the c++ primer defines a "class" using the struct keyword starting on p. 72-73. Here's a small excerpt with the code:
"Defining the Sales_data Type
Although we can’t yet write our Sales_item class, we can write a more concrete class that groups the same data elements. Our strategy for using this class is that users will be able to access the data elements directly and must implement needed operations for themselves.Because our data structure does not support any operations, we’ll name our version Sales_data to distinguish it from Sales_item. We’ll define our class as follows:"
struct Sales_data {
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
This book is suppose to be an authoritative overview of C++11, so why would they use the keyword struct instead of class to describe a class type?
It's common use to define POD types as struct and data types which contain other members, constructors, methods, etc. as class. They are basically the same, the difference being the members are public by default in a struct and private by default in a class.
The usage in the book is consistent with the above description.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
On our current project, we are currently having issues with the way we are handling constants. To try to sum it up, let's say we have different action types, defined as const std::string
const std::string actionTypeX = "XXX";
const std::string actionTypeY = "YYY";
...
Those action types may have different properties, which makes them trigger different behavior. This is usually implemented through an std::unordered_map, linking the action type to whatever property we need :
const std::unordered_map<std::string, int> actionFlow = {
{ actionTypeX, DB_FLOW },
{ actionTypeY, DRL_FLOW },
.... };
Those maps are usually used in one single implementation, so we put them in anonymous namespaces in the corresponding CPP file. On the opposite, the constants strings are usually used by many files and so are defined in a common constants file.
The issue we have is that we end up having the infamous static initialization order fiasco: Some maps are using common strings that are not yet initialized, generation a segmentation fault.
The known solution for this issues are:
Put all maps that depends on those constants in the same file, thus avoiding the problem of the order. But this would create a huge, ugly file which might be difficult to maintain
Put those maps within a static function returning a reference to a static map, but in my opinion it does look a bit 'hacky'
While both solutions should work, I feel they would just be a workaround for a design problem of our application.
So my question is, how should a C++ program with many constants be designed so it is easily maintainable ?
Thank you,
Regards,
How about not using std::string for constants:
constexpr auto actionTypeX = "XXX";
By using constexpr you no longer face the issues related to static intialization fiasco. You can then safely use this constants to initialize your maps.
Furthermore, you can then use std::string_view as the keys (that's assumed you only use the global constants as the keys anyway) in the maps to get some more flexibility and keep the maps lightweight.
Put those maps within a static function returning a reference to a static map, but in my opinion it does look a bit 'hacky'
I would go with this approach, but possibly encapsulate it a bit more. It seems like the std::unordered_map is an implementation detail, and all you need to expose is the access to the constants.
Library:
A little helper that hides the static initialization can be useful. You would put this in a header to include whenever you need to define constants:
// T = value, Init = functor to initialize constants
template <typename T, typename Init>
class Constants
{
static std::unordered_map<std::string, T>& constants()
{
static bool initialized = false;
static std::unordered_map<std::string, T> map;
if (!initialized) // alternative: map.empty()
Init()(map);
return map;
}
public:
static T get(const std::string& key)
{
return constants()[key];
}
};
Constant definition:
In a concrete .cpp file, you could use it as follows:
// Your function for initialization
struct ActionFlowInit
{
void operator()(std::unordered_map<std::string, int>& map) const
{
map["one"] = 1;
map["two"] = 2;
}
};
using ActionFlows = Constants<int, ActionFlowInit>;
In a real scenario, you would expose the functor in the header, but leave the implementation of its operator() to the .cpp file, in order to abstract away the actual constants.
If you don't want to settle for std::unordered_map, the signature can of course be more generic -- just pass a parameter to operator() which allows you to register a constant.
Constant usage:
Access the constants like this:
int x = ActionFlows::get("one");
It's of course possible to add more syntactic sugar, especially for the initialization. boost::list_of can be an inspiration.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
In C++, which of these ways is better?
// this is class, not a struct (just means members are public by default)
struct foo {
int w, h;
private:
public:
};
Or
class foo {
private:
int w, h;
public:
int getW() { return w; }
int getH() { return h; }
};
In this case:
foo *A;
If I'm trying to get the values of w and h,
should I use A->w and A->h for the first example or A->getW() and A->getH() for the second example?
Right now I'm using the first example, but is it in any way better practice to make methods to return the private variables? Is there some advantage to one way over the other?
If this is your only concern, then there is no practical difference. If you intend to only have members that are visible to the outside via accessor methods, then they might as well be made public (or a POD.) For example:
struct SomeSortOfInformation
{
int w, h, x, y, pixelFormat, whatever;
};
If you intend to protect implementation details, or to change the behavior of accessing a variable (i.e., this is a common idiom in C#), then feel free to use accessor methods.
void setWidth(const int& w) {
if (w <= 0) this->w = 0;
else this->w = w;
}
The immediate difference is that users of the class can assign to the values of w and h in the first example, but not the second.
The difference for future code changes is that the author of the class can change the way that foo's data is stored in the second example, but not the first. For example if the class represents a rectangle, then you could switch to storing the co-ordinates of the corners, and calculate the width and height when requested.
There is no certain way that is "better". If you have a class that is defined to be a dumb data container, that users can read from and write to, and it is guaranteed that it will not in future perform any clever calculations, then you can use public data members. An example of this in the standard libraries is std::pair, which has public data members first and second. Many OOP programmers will (on principle) never define or document any such guarantee, but the designers of the C++ standard libraries do not agree with this absolute principle. In any case C++ is not designed on strict OOP principles.
If you have a class that just so happens to store values that are useful to the user, but is not guaranteed to store them as members, then you would use accessors if necessary. An example in the standard libraries is std:vector, which has functions begin() and end(). In some implementations of vector they just return the values of two private data members, in other implementations they do something else.
If possible, though, give the class the functionality that the user needs, so that they don't need public data or accessors. An example in the standard libraries is std::stack, which has a protected data member for use by derived classes, but does not give "normal" users any direct access to it. If you find yourself routinely writing accessors for most data members of most classes you write, then you should seriously consider whether your design can be improved. Accessors mean that users of your class must provide the logic to use the data member. But the main advantage of classes is the ability to keep the logic for using data in the same place that the data is defined. If users always provide the logic then you're not using that opportunity.
By the way, there are a couple of errors in your question:
this is class, not a struct
It is a struct. It is also a class type.
int getW() { return w; }
Getters should be const functions: int getW() const { return w; }
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
class test {
public:
test(int value = 0): x(value) {}
int& get(){
return x;
}
private:
int x;
};
this will allow client code to mutate the private members
this is legal in C++, but why ?
Is there any situation where you would actually need to break the class encapsulation ?
Make a member as private, means you can not access it directly. But nothing restricts you to access it indirectly via a public member. It depends on you design. You can even do this:
class test {
public:
test() : x(y) {}
int &x;
private:
int y;
};
In your class, assume you want count how many times a member is read/write. So, you can make it private then put a member function which returns a refernce to the variable:
class test {
public:
test(int value = 0): x(value), count(0) {}
int& get(){
count++;
return x;
}
private:
int x;
int count;
};
I hope this example shows how making a member as private and then putting an indirect access to it can be useful.
Ffirst of all let's consider implementing what you describe. It would be very onerous to properly do so. Your example is easy enough. But what if the reference flowed through a number of functions before it reached the function that exposed it? The compiler would have to do exceptionally complex static analysis, beyond the levels of static analysis that are reasonable to expect from compiler writers.
So even if the designers wanted to ban this, it would not have been tractable to do so. Would the designers have wanted to stop this? Very doubtful. Had they done so, how would the [] operator be implemented on a container or a string?
Is there any situation where you would actually need to
break the class encapsulation
As example of the [] operator on containers and strings shows, this feature is in fact used to support encapsulation.
Why? Because C++ mainly tries to let you do whatever you want and not get in your way; it doesn't try very hard to keep you safe. If you want a safe language, use something else. You have something like object-orientation if you want to, but if you want to break out of that, more power to you. With great power comes great responsibility.
It's worth nothing that you don't even need this to break encapsulation; you could simply reinterpret a pointer to "test" as an integer and access the private field this way.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I put 'sets' just after the constructors because it is related to the object setup. I split gets (put gets in inquires) and sets but not sure if this is good or not. What is best practice for organizing member functions?
How about that?
class Foo
{
// Friends go here if it has
friend ...;
friend ...;
// First public, then protected and private
public:
// enums
enum {...}
// type defines.
typedef ...;
...
// Destructor and constructors
~Foo();
Foo(...);
Foo(...);
...
// Sets.
void setA(...);
void setB(...);
void setC(...);
...
// Inquiries (including gets).
A a() const;
B b() const;
...
// Operators.
void operator()(...);
...
// Operations.
void doSomething();
...
protected:
private:
};
It's hard to judge, it's up to your personal preference or company coding standard. By looking at your code, a few things I may not agree:
your declarations are not ordered from pubilc,'protected` then private
friend declaration has same effort when you declare them in private area as well. so I normally put them in private section, so it gives less noise in public section.
Below is the declaration order I normally use:
Use the specified order of declarations within a class: public: before private:, methods before data members (variables), etc.
class definition should start with its public: section, followed by its protected: section and then its private: section. If any of these sections are empty, omit them.
Within each section, the declarations generally should be in the following order:
Typedefs and Enums
Constants (static const data members)
Constructors
Destructor
Methods, including static methods
Data Members (except static const data members)
Friend declarations should always be in the private section, and the disabled copy constructor and other operators `should be at the end of the private: section. It should be the last thing in the class.