从头文件声明创建 C++ 实现的宏





0/5 (0投票)
从头文件声明开始,这个宏会打开 .cpp 文件并创建框架,以便您可以开始添加实现。这使得添加函数变得轻而易举,因此现在真的没有借口再写出糟糕的未重构代码了。
本迷你系列中的第二个宏非常有用。从头文件声明开始,它会打开 .cpp 文件并创建框架,以便您可以开始添加实现。这使得添加函数变得轻而易举,因此现在真的没有借口再写出糟糕的未重构代码了。它使用 切换到源文件的宏,因此如果您想知道它是如何工作的,请务必查看该文章。
这个宏的工作方式如下
- 您在头文件中输入声明
- 您运行该宏
- 函数框架将被创建并添加到您的 .cpp 文件中,准备好供您开始在主体中键入
首先,我们将编写一个函数来查询 代码模型,并获取光标所在的函数。
Private Function GetFunction() As EnvDTE.CodeFunction
Dim textSelection As EnvDTE.TextSelection
Dim codeFunction As EnvDTE.CodeFunction
textSelection = DTE.ActiveWindow.Selection
codeFunction = textSelection.ActivePoint.CodeElement(vsCMElement.vsCMElementFunction)
Return codeFunction
End Function
在这里,我们只是查找光标在窗口中的位置,并找到它下面的函数。 CodeFunction 是一个 Visual Studio COM 对象,它允许我们探索我们编写的代码。
如果您只想复制和粘贴,我将首先向您展示整个宏,然后我将逐步讲解。
Sub CreateImplementation()
Dim func As EnvDTE.CodeFunction = GetFunction()
Dim params As StringBuilder = New StringBuilder()
Dim item As CodeParameter
For Each item In func.Parameters
If (params.Length > 0) Then
params.Append(", ")
End If
params.AppendFormat("{0} {1}", item.Type.AsFullName(), item.FullName)
Next
' Build up the line from the function
Dim funcBody As StringBuilder
funcBody = New StringBuilder()
funcBody.AppendFormat("{0} {1}({2})", _
func.Type.AsFullName(), func.FullName, params.ToString())
If (func.FunctionKind And vsCMFunction.vsCMFunctionConstant) Then
funcBody.Append(" const")
End If
funcBody.AppendLine()
funcBody.AppendLine("{")
funcBody.Append("}")
' Move to cpp file
ToggleBetweenHeaderAndSource()
' Move to end of document
DTE.ActiveDocument.Selection.EndOfDocument()
DTE.ActiveDocument.Selection.NewLine(2)
' Insert the function
DTE.ActiveDocument.Selection.Text = funcBody.ToString()
' Move cursor into function
DTE.ActiveDocument.Selection.LineUp()
DTE.ActiveDocument.Selection.NewLine(1)
End Sub
您现在可以停止复制了。这是分析
Sub CreateImplementation()
Dim func As EnvDTE.CodeFunction = GetFunction()
在这里,我们创建函数以获取函数,如上所述。如果我讲得太快,请告诉我。
Dim params As StringBuilder = New StringBuilder()
Dim item As CodeParameter
For Each item In func.Parameters
If (params.Length > 0) Then
params.Append(", ")
End If
params.AppendFormat("{0} {1}", item.Type.AsFullName(), item.FullName)
Next
这是一个有趣的部分。然后我们查询 CodeFunction
对象。我们从 Parameters
集合中提取每个参数,并根据每个参数的类型和名称构建一个 string
。
因此,如果我们的函数原型是 void EatBiscuits(int amount, bool unwrapFirst);
,我们目前正在构建 int amount, bool unwrapFirst
部分。
Dim funcBody As StringBuilder
funcBody = New StringBuilder()
funcBody.AppendFormat("{0} {1}({2})", _
func.Type.AsFullName(), func.FullName, params.ToString())
接下来,我们找到函数名及其返回类型,并构建该部分的字符串。然后,我们添加之前发现的参数。关键部分是 func.FullName
。这将找到类名和命名空间,以便我们完全限定实现函数名。
我们也可以丢弃诸如 virtual
和 static
之类的限定符。
If (func.FunctionKind And vsCMFunction.vsCMFunctionConstant) Then
funcBody.Append(" const")
End If
但我们需要检查的是 const
成员函数,并在需要时将其追加到 const
。
funcBody.AppendLine()
funcBody.AppendLine("{")
funcBody.Append("}")
在这里,函数主体被创建。如果您希望 {
放在函数声明的末尾而不是新的一行,您可以调整它,但这取决于您是否奇怪。我喜欢遵循缥缈的 WebBiscuit 编码标准,并为大括号单独留一行。
ToggleBetweenHeaderAndSource()
DTE.ActiveDocument.Selection.EndOfDocument()
DTE.ActiveDocument.Selection.NewLine(2)
现在我们调用 切换到 cpp 定义的宏,移动到文档的末尾,并插入几行空白行。我承认这里的两个完全是任意的,可能是有缺陷的。如果您的文件末尾有 20 行空白行,这将从第 22 行开始。也许您可以改进这一点。
DTE.ActiveDocument.Selection.Text = funcBody.ToString()
DTE.ActiveDocument.Selection.LineUp()
DTE.ActiveDocument.Selection.NewLine(1)
现在是最后一部分,也是最令人满意的部分。我们将函数主体字符串放置在 cpp 文件中的当前位置。然后我们将光标向上移动一行(因为光标当前位于结束大括号的后面一个字符处)。然后插入一个空行,以便可以直接在此主体中开始键入。
Time saved: at least 10 seconds
Time spent writing macro and blog article: ages
Biscuits eaten: lots
我没有抱怨。我学到了很多东西,并且这个宏非常有用。当您处于编程状态时,那几秒钟可能至关重要!
我不喜欢的事情
如果您在 namespace
中有一个 class
,生成全名将限定为:namespace::classname::functionname
。但我看到 Visual Assist 也是这样做的,所以也许没关系。
限制
- 它尚未干净地处理构造函数或析构函数。它在开头放一个
void
。欢迎提出想法。 - 如果您正在编写一个独立的函数,该宏不起作用。目前,函数定义必须在一个类中。我们将在后续的文章中修复这个问题。