当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ - Exposing template member field

问题描述:

It is generally a bad idea to expose the internal structure of a class:

class MyClass {

public:

double& Val() { return m_val; } // <---------- Bad

double const& Val() const { return m_val; }

private:

double m_val;

};

But what about:

template <typename T>

class MyClass {

public:

T& Val() { return m_val; } // <---------- Bad/Good?

T const& Val() const { return m_val; }

private:

T m_val;

};

Now the user of that class already knows of the existence or at least reliance of MyClass<T> on type T (he chose T).

Is it any better than the first case?

EDIT:

The reason I need to access m_val from the outside is to modify it in some way. Say use a non-const method. const won't do here.

To add some context. T is a type from the user domain that implements an interface MyClass could use (and other domain specific functionality). The user knows that MyClass has type T member as MyClass has to constructors:

  1. MyClass(T& val) //From user - has "val" in user scope. No need to expose
  2. MyClass(int id) //From external source by id - no "val" in user scope. Expose?

EDIT:

If I was coping only with a non-template scenario then I would add the functionality required to handle m_val to MyClassinterface. However, as I don't know anything about T I can't do it without getting into messy partial template specialization which would increase the amount of code significantly and would require modifications to MyClass<T> any time T changes

网友答案:

Unless I have serious reason to do otherwise I try to stick with

T const& GetVal() const;
void SetVal( const T& val );

Clients can guess from the 1st signature that you are storing a variable of type T somewhere. But I can live with this for the sake of performace. Another option would be to return T by value. But this could cause an extra copy.

网友答案:

Generally it's something to avoid as it breaks encapulation, and prevents the class from managing it's own internal data.

But it's not bad practice on it's own, it's how you use it. std::vector obviously does just this and that's reasonable...

网友答案:

If you think about the reasons for avoiding these...

double& Val() { return m_val; } // <---------- Bad
double const& Val() const { return m_val; } 

...you can assess whether the impacts are less "bad" for template.

The reasons this was "bad" include:

  • You need to have a variable somewhere for both Val() functions to return a reference to, and you have no real control over how long the client code will expect it to be valid or what they'll do with it. That means you can't enforce invariants about the data member, you can't provide internal locking to make get/set operations thread safe, you can't change the implementation to remove the double and calculate the value on the fly or encode the value being set in some different way.

  • In many cases, get/set functions are the wrong way to build an interface, and the focus should be on asking the class to perform operations rather than fiddling with specific parts of it's data. Still, that's a generalisation and there are plenty of cases where data members are validly exposed.

Macros make no difference to either of these issues.

网友答案:

In your second suggestion you are not only returning the same internal variable, but you are also making the user think that this variable somehow depends on the type fed to the template. In your case, I believe, the type of the variable is totally irrelevant to anything at all (since you had the first version initially, I believe it's the only one you need, otherwise you would have had a template right away), so using a template here is confusing and pretty useless. Sorry if that last sentence was confusing...

Moreover, you are not exposing the internal structure of the class here. Using setters and getters (which is your case here) is a way to hide the structure, so it's fine.

分享给朋友:
您可能感兴趣的文章:
随机阅读: