class User {
public:
int v() {
return min_pass_len;
}
static const int min_pass_len = 10;
};
class AdminUser : public User {
public:
int w() {
return min_pass_len;
}
static const int min_pass_len = 42;
};
然后
int main() {
AdminUser a;
std::cout << a.v() << " why? " << a.w() << std::endl;
return 0;
}
我可以以某种方式避免额外的方法调用吗?我也对其他解决方案,最佳实践感兴趣。谢谢!
答案 0 :(得分:3)
只需使用返回不同数字的虚方法,跳过静态变量。
class User {
public:
virtual int v() {
return 10;
}
};
class AdminUser : public User {
public:
virtual int v() {
return 42;
}
};
答案 1 :(得分:1)
您错过了virtual
关键字。在C ++中,默认情况下,方法不是虚拟的,就像它们在某些其他编程语言中一样(例如,Java)。请尝试以下方法:
#include <iostream>
class User {
static const int min_pass_len = 10;
public:
virtual ~User() {}
virtual int getPasswordLength() const {
return min_pass_len;
}
};
class AdminUser: public User {
static const int min_pass_len = 42;
public:
virtual ~AdminUser() {}
virtual int getPasswordLength() const {
return min_pass_len;
}
};
int
main()
{
AdminUser a;
User u, *p = &a;
std::cout
<< u.getPasswordLength() << "\n"
<< a.getPasswordLength() << "\n"
<< p->getPasswordLength() << "\n"
<< std::endl;
return 0;
}
如果你想完全摆脱这个方法,那么要么使用"curiously reoccuring template pattern" mentioned by Sanjit的例子,要么外化常量而不是将它嵌入到类中。我在考虑类似于std::numeric_limits
的实现方式:
template <typename T>
struct UserTraits {
static const int minimum_password_length = 0;
};
template<> struct UserTraits<User> {
static const int minimum_password_length = 10;
};
template<> struct UserTraits<AdminUser> {
static const int minimum_password_length = 10;
};
int main() {
std::cout
<< UserTraits<User>::minimum_password_length << "\n"
<< UserTraits<AdminUser>::minimum_password_length << "\n"
<< std::endl;
return 0;
}
我通常更喜欢第一种方法,因为它有一个指向实例的指针。后一种方法几乎没有用,因为你不能使用它从实例中提取常量而不需要编写自由函数,即使你失去了动态类型的方面。
template <typename T>
int getPasswordLength(T*) {
return UserTraits<T>::minimum_password_length;
}
template <typename T>
int getPasswordLength(T&) {
return UserTraits<T>::minimum_password_length;
}
这种方法的问题在于,如果您在第一个代码段中使用getPasswordLength(p)
调用p
,则会得到错误的结果。
答案 2 :(得分:1)
最佳做法会建议使用virtual
函数(这就是为什么它们被引入,以使旧代码能够调用新代码):
class base{
public: virtual int get_magic(){return 10;};
};
class der1: public base{
public: virtual int get_magic(){return 42;};
};
然而,在基类中定义的一个简单变量,但在每个派生的构造函数中重写会更快,并且会消除任何调用(因为它将被内联):
class base{
protected: int magic; // note that it's not static!
public:
base(){magic = 10;};
int get_magic(){return magic;};
};
class der1: public base{
public:
der1(){magic = 42;};
};
答案 3 :(得分:0)
如果你想为不同的派生类设置不同的常量,你应该像这样模板化基类:
template<class T>
class User
{
// Make the password len getter virtual.
virtual GetPassLen() { return min_pass_len; }
...
static const int min_pass_len = 10;
}
class AdminUser : public User<AdminUser>
{
}
// All admin users get this constant
AdminUser::min_pass_len = 42;
class GuestUser : public User<GuestUser>
{
}
// Guest user can have a different constant than Admin user.
Guestuser::min_pass_len = 0;