微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

头文件和源文件中的typedef返回类型-最佳实践是什么?

如何解决头文件和源文件中的typedef返回类型-最佳实践是什么?

我有一个带有成员函数且返回类型很长的类:

/* MyClass.hpp */
namespace foo 
{
  class MyClass
  {
  public:
    SomeNameSpace::Lengthy_return_type_name someFunction(params...); 
  };
}

我想使此内容更具可读性,而不会使读者感到困惑,并且我不必将typedef暴露给外界。因此,在MyClass.hpp中,我在MyClass中添加了以下typedef:

/* MyClass.hpp */
namespace foo 
{
  class MyClass
  {
  private:
    typedef SomeNameSpace::Lengthy_return_type_name myType;
  public:
    myType someFunction(params...); 
  };
}

现在,在MyClass.cpp中,我遇到了一个难题,因为看不到myType可以用作返回类型。如果我将typedef公开,我可以使用MyClass :: myType,但是我不喜欢那样,因为我认为它令人困惑并且也暴露了myType。我还可以将typedef添加到MyClass.cpp的顶部,但这可能会使含义失去意义,因为读者将不得不进行一些挖掘来找出类型所指的内容

我是否想得太多?在这种情况下,最佳做法是什么?

解决方法

简短的答案是:公开别名。没有理由将其设为私有。

为便于说明,我将您的示例再进一步一步。假设myType不仅是别名,而且是一种新类型:

struct foo {
    private:
       struct myType {};
    public:
       myType someFunction();
};

现在让我们看看这会带来什么:myType真的是私有的吗?不。

呼叫者可以做

 foo f;
 auto x = f.someFunction();
 using myMyType = decltype(x);

Tada,用户具有myType的别名myMyType。公共函数的返回类型不是私有的!只有名称foo::myType是私有的,但是由不同名称引用的类型是常见的。试图隐藏该名称没有任何意义。您获得的唯一结果就是强制用户使用其他名称。

还要考虑可能会有这个定义

 foo::myType foo::someFunction() {}

无法编译,因为foo::myType是在foo的专用部分中定义的。但是,公共方法的返回类型不能真正私有。如果不允许上述定义,则可以编写:

 decltype( declval<foo>().someFunction() ) foo::someFunction() {}

因此禁止上述定义真的没有意义。

Live example

,

绝对想得太多,因为您的呼叫者无论如何都需要具有完整的定义。限制访问他们必须知道的内容毫无意义。

此外,当将typedef用作返回类型时,对调用者隐藏using myType = SomeNameSpace::Lengthy_return_type_name;有什么意义?它不会买任何东西,在这种特殊情况下没有封装。

最后,我是否建议您切换到现代语法以完成相同的工作?

async function getBase64ImageFromUrl(imageUrl) { var res = await fetch(imageUrl); var blob = await res.blob(); return new Promise((resolve,reject) => { var reader = new FileReader(); reader.addEventListener("load",function () { resolve(reader.result); },false); reader.onerror = () => { return reject(this); }; reader.readAsDataURL(blob); }) } getBase64ImageFromUrl('https://graph.facebook.com/3938027626271800/picture?type=normal') .then(result => console.log(result)) .catch(err => console.error(err));

您最终会喜欢上它的,因为它提供的内容远远超过普通的typedef,例如alias templates

,

在开始时定义所有类型是一个好主意。

只需看一下标准库的任何类实现:vector为例。 “成员类型部分”由有用的typedef填充。

如果查看实现细节,则一般方案为:

@Component({
  template: '<td>{{objectKeys(myObj)[0]}}</td>'
})
export class MyComponent {
  objectKeys = Object.keys;

  myObj = { displayThisKey: 'some-value' };
}

如果该方法是公共的,则也应将typedef声明为公共的。保持连贯一致。


正如其他人所述,自C ++ 11起,最好使用template<typename _Tp,typename _Alloc = std::allocator<_Tp> > class vector : protected _Vector_base<_Tp,_Alloc> { typedef _Vector_base<_Tp,_Alloc> _Base; typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; // ... public: typedef _Tp value_type; typedef __gnu_cxx::__normal_iterator<pointer,vector> iterator; typedef __gnu_cxx::__normal_iterator<const_pointer,vector> const_iterator; // ... public: iterator begin(); const_iterator begin() const; // ... }; 而不是using,请参见What is the difference between 'typedef' and 'using' in C++11?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。