65.9K
CodeProject 正在变化。 阅读更多。
Home

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

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2011年12月17日

CPOL

3分钟阅读

viewsIcon

14909

downloadIcon

105

从头文件声明开始,这个宏会打开 .cpp 文件并创建框架,以便您可以开始添加实现。这使得添加函数变得轻而易举,因此现在真的没有借口再写出糟糕的未重构代码了。

本迷你系列中的第二个宏非常有用。从头文件声明开始,它会打开 .cpp 文件并创建框架,以便您可以开始添加实现。这使得添加函数变得轻而易举,因此现在真的没有借口再写出糟糕的未重构代码了。它使用 切换到源文件的宏,因此如果您想知道它是如何工作的,请务必查看该文章。

这个宏的工作方式如下

  1. 您在头文件中输入声明
  2. 您运行该宏
  3. 函数框架将被创建并添加到您的 .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。这将找到类名和命名空间,以便我们完全限定实现函数名。

我们也可以丢弃诸如 virtualstatic 之类的限定符。

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。欢迎提出想法。
  • 如果您正在编写一个独立的函数,该宏不起作用。目前,函数定义必须在一个类中。我们将在后续的文章中修复这个问题。
© . All rights reserved.