避免在类头文件中声明私有函数(C++)

问题描述 投票:0回答:5

(在 C++ 中)我有一个类,其结构在头文件中声明。该头文件包含在很多源文件中,因此当我编辑它时,我需要重新编译很多文件。

该类有一组私有函数,仅在一个源文件中调用。目前它们在头文件的类结构中声明。当我添加这种类型的新函数或编辑参数时,它会导致重新编译大量文件。我想在其他地方声明这些函数,这样只有定义和调用它们的文件才会被重新编译(以节省时间)。不过,他们仍然需要能够访问内部类变量。

我怎样才能实现这个目标?

c++ function header private declare
5个回答
14
投票

使用 pImpl 习惯用法 - 您的可见类保留指向 real 类的指针,并将调用转发到公共成员函数。

编辑:回应评论

// Foo.h:

class FooImpl; // Do *not* include FooImpl.h
class Foo {
public:
  Foo();
  ~Foo();
  //.. also need copy ctor and op=
  int bar();
private:
  FooImpl * Impl;
};

// FooImpl.h:

class FooImpl {
public:
  int bar() { return Bar; }
private:
  int Bar;
};

// Foo.cpp:

#include "FooImpl.h"

Foo::Foo() { Impl = new FooImpl(); }
Foo::~Foo() { delete Impl; }
int Foo::bar() { return Impl->bar(); }

将类的实际实现保留在

FooImpl
中 -
Foo
应该具有 FooImpl
public
成员的副本,并将调用转发到这些成员。所有用户将仅包含“Foo.h” - 您可以更改
FooImpl
的所有私人详细信息,而
Foo
的用户不会看到任何更改。


6
投票

无法在主类声明之外声明类的成员函数。因此,如果您想在相关类之外声明可以访问该类特定实例的成员变量的函数,那么除了将该实例传递给该函数之外,我别无选择。此外,如果您希望函数能够访问私有变量和受保护变量,您需要将它们放入一个新类中,并使原始类成为该类的友元。例如

标题.h:

class FooImpl;

class Foo {
public:
   int bar();
   friend class FooImpl;
private:
   int var;
}

impl.cpp:

#include "header.h"

class FooImpl {
public:
   int bar(Foo &);
}

int FooImpl::bar(Foo &foo) {
return foo.var;
}

int Foo::bar() {
return FooImpl::bar(*this);
}

2
投票

您是否在寻找编译器防火墙,又名 PIMPL?


1
投票

创建一个仅包含公共函数的抽象基类,并在标头中引用它。创建您的真实类作为其他地方的实现。只有需要创建类的源文件才需要查看实现类头。


0
投票

这是一个干净的解决方案(没有动态分配或指针重定向)。 将变量和公共函数保存在SomeClass中,并在SomeClass_Impl中编写实现。 这些 Impl 函数也可以移动到源文件(如果您喜欢完全干净的头文件)。

.h

#pragma once

//forward declare the private 
struct SomeClass_Impl;

//public struct with public functions
struct SomeClass
{
    float Values[4] = {};

    SomeClass_Impl* Impl() { return (SomeClass_Impl*)this; }
    const SomeClass_Impl* Impl() const { return (const SomeClass_Impl*)this; }

    void Print() const;
};

.cpp

#include "SomeClass.h"
#include <iostream>

//private implementation, should only contains functions
struct SomeClass_Impl : SomeClass
{
    float GetSum() const
    {
        float Sum = 0;
        for(float V : Values)
            Sum += V;

        return Sum;
    }
    float GetMinValue() const
    {
        float MinVal = Values[0];
        for (int i = 1; i < 4; i++)
            MinVal = std::min(MinVal, Values[i]);

        return MinVal;
    }
};

static_assert(sizeof(SomeClass) == sizeof(SomeClass_Impl), "_Impl should not have any member variables.");


void SomeClass::Print() const
{
    //'this' can be casted to SomeClass_Impl without any cost   
    std::cout << "Sum:" << Impl()->GetSum() << " MinValue:" << Impl()->GetMinValue() << '\n';
}

用途:

SomeClass A;
A.Values[0] = 1;
A.Values[1] = 2;
A.Values[2] = 3;
A.Values[3] = 4;

A.Print();
© www.soinside.com 2019 - 2024. All rights reserved.