如何避免访问受保护的类成员?

3

我在很多讨论中读到,拥有受保护的类成员是不好的,我也看出了其中的原因。但是,在下面的例子中,最优雅的方法是什么来使 const int age 成为 private 并解决由此引起的问题?

#include <iostream>

class Animal
{
    public:
        Animal(const int age) : age(age) {}
        void print_age() const { std::cout << age << std::endl; }
    protected:
        const int age;
};

class Dog : public Animal
{
    public:
        Dog(const int age) : Animal(age) {}
        void bark() const
        {
            if (age >= 1)
                std::cout << "Woof!" << std::endl;
            else
                std::cout << "(...)" << std::endl;
        }
};

int main()
{
    Dog dog(1);
    dog.print_age();
    dog.bark();
    return 0;
}

int getAge() const{ return age; } 的翻译是什么? - default
如果你将 age 设为私有的,那么你需要添加访问器(即 get 和 set)。但是你会将它们设为公共的吗?年龄是否应该在动物层次结构之外被修改?如果不是,你必须将其设为受保护的,然后你又回到了同样的问题。 - Marius Bancila
@Default,使用访问器函数从基类检索变量是不是有点奇怪? - Chiel
@MariusBancila,在程序中没有任何年龄是常量且不被修改的。 - Chiel
1个回答

7
如果你在参考类似于为什么Clean Code建议避免使用受保护的变量这样的原因,你还需要记住,这些指南是针对现实世界场景而设计的,那里的继承层次结构通常不像动物和狗那样清晰。对于企业级应用程序,许多开发人员很容易想到继承,认为它能够在未来带来更多组织,但实际上变量被轻率地放入基类中,随着时间的推移,导致结构膨胀并侵蚀其成员的组织上下文。

在你的简单情况下,使用protected是可以的。


总的来说,我的解决方案是有意义的,对于结构简单的程序来说,在我使用的方式中使用“protected”是可以的。 - Chiel
1
它确实如此。然而,在更大的应用程序上下文中,如果在可预见的未来没有支持除了狗之外的任何动物的需要,并且您开始将“年龄”以及其他成员放入基类中,那么这种做法就没有意义。但当然,在这种情况下,您也不应该创建“动物”。(将此示例类比于更真实的世界有点棘手。) - Andrew Cheong
1
你问如何避免使用 protected。如果问题是你正在使用不需要的继承体系,那么答案就是:摆脱 Animal。但显然你有一个使用 Animal 的好理由,所以这个建议没有意义。在现实世界中,有时确实是这样的答案:“你一开始就使用了错误的结构。”或者至少,“只需将其放入派生类中,您将不会在其他类中使用它。”(但对于你的例子来说,这也没有意义,因为 age 确实是 Animal 通用的属性。) - Andrew Cheong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接