我有一个基类Base
,有许多派生类(例如Derived1
,Derived2
)。 Base
具有纯虚函数fn
,使用Base
指针多次调用。每次调用该函数时,我都需要做一些额外的日志记录和相关的东西。特别是,我在derived-class函数中使用BOOST_CURRENT_FUNCTION
来找出调用的函数。有没有办法在调用函数之前知道这些信息,这样我就不必在每个派生函数中重写簿记代码了?
编辑:我希望避免在每个派生函数中编写__PRETTY_FUNCTION__
。
#include <iostream>
using namespace std;
class Base {
public:
virtual void fn() = 0;
};
class Derived1:public Base {
public:
void fn() {
cout<<__PRETTY_FUNCTION__<<endl;
}
};
class Derived2:public Base {
public:
void fn() {
cout<<__PRETTY_FUNCTION__<<endl;
}
};
int main()
{
int choice =0;
Base *ptr1 = nullptr;
cout<<"Choose 0/1: "<<endl;
cin>>choice;
if(choice == 0) {
ptr1 = new Derived1;
}else {
ptr1 = new Derived2;
}
//********CAN I WRITE SOMETHING HERE, TO GIVE THE SAME RESULT?
ptr1->fn();
}
答案 0 :(得分:1)
根据您的描述,您似乎有一个设计问题。您考虑过使用template method design patter吗?我们的想法是让您的基类实现通用功能,并通过虚函数实现派生类中的细节。
答案 1 :(得分:1)
一个想法是实现基本纯虚函数并在每个派生覆盖中调用它。在基础中,您可以增加一个静态计数器。类似的东西:
#include <iostream>
#include <memory>
struct Base
{
static size_t counter;
virtual void f() = 0;
virtual ~Base() = default;
};
size_t Base::counter{0};
void Base::f() // IMPLEMENTATION, yes it's possible to implement a pure virtual function
{
++counter;
}
struct Derived1: Base
{
void f() override
{
Base::f(); // increment the counter
std::cout << "Derived1::f()\n";
}
};
struct Derived2: Base
{
void f() override
{
Base::f(); // increment the counter
std::cout << "Derived2::f()\n";
}
};
int main()
{
std::unique_ptr<Base> pBase1{new Derived1};
std::unique_ptr<Base> pBase2{new Derived2};
pBase1->f();
pBase1->f();
pBase2->f();
std::cout << Base::counter << std::endl; // outputs 3
}
如果我没错,我相信这是模板方法设计模式mentioned by @LordDosias的一个实例。没有其他内在的方法可以从语言中获取这些信息,因为C ++没有真正的运行时反射功能。
答案 2 :(得分:1)
不,它不可能。 C ++不支持这种内省。 __PRETTY_FUNCTION__
就是你要去的所有。
答案 3 :(得分:0)
好吧,除了将宏包装在另一个更小/更短/更多的宏中之外,没有什么可以为你提供一个函数的名称。
#define WHERE cout << __PRETTY_FUNCTION__ << endl
...
void fn() {
WHERE;
}
这也意味着您可以轻松打开/关闭跟踪:
#if TRACING
#define WHERE cout << __PRETTY_FUNCTION__ << endl
#else
#define WHERE
#endif
(您可能希望将其包含在do { ... } while(0)
的两边以避免出现问题,如果您要将WHERE
置于if或某些内容中,并且仍然希望它在以下情况下正常工作它&#34;什么都不是&#34;)
答案 4 :(得分:0)
最简单的答案是,由于C ++没有辅助方法,您必须将fn
的实现拆分为实用程序包装器和虚函数:
class Base {
protected:
virtual void fn_impl() = 0;
public:
void fn() { fn_impl(); }
};
class BaseWithLogging: public Base {
public:
void fn(); {
/* do logging */
fn_impl();
}
};
如果您希望日志捕获实际的虚拟(功能名称,文件,行号等)的确切标识,则没有解决方法;样板必须进入功能。
硬壳旧的预处理器可以提供帮助。例如。头脑简单的插图:
#define LOG (cout<<__PRETTY_FUNCTION__<<endl)
然后你就有了
LOG;
在函数的开头。