簡體   English   中英

谷歌測試使用 Bazel 錯誤 - `在平面命名空間中找不到符號`

[英]Google test using Bazel error - `symbol not found in flat namespace`

我最近開始學習 C++(來自 Python 背景)和 Bazel 構建系統。 我有一個非常簡單的玩具設置來習慣在 Bazel 上使用 GoogleTest。 這是我的文件 -

我的文件和目錄結構如下——

.
  WORKSPACE
  main/
    shape.cc
    shape.h
    BUILD
  test/
    shape_test.cc
    BUILD

文件內容如下——

# WORKSPACE file - from http://google.github.io/googletest/quickstart-bazel.html

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
  name = "com_google_googletest",
  urls = ["https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip"],
  strip_prefix = "googletest-609281088cfefc76f9d0ce82e1ff6c30cc3591e5",
)

# main/BUILD


load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
package(default_visibility = ["//visibility:public"])


cc_library(
    name = "shape",
    srcs = ["shape.cc"],
    hdrs = ["shape.h"],
)


// main/shape.h

#include <string>
#include <vector>
class AbstractShape
{
protected:
    float area;
    float perimeter;
    std::string shape_name;

public:
    float get_area();
    void describe();
    virtual std::string get_description();
};

AbstractShape factory_method(float h, float w, std::string colour = "", std::string surface = "");

float calculate_area(std::vector<AbstractShape> shape_arr);

class Rectangle : public AbstractShape
{

public:
    Rectangle(float h, float w);
    std::string get_description();
};

class ColourAndSurfaceRectangle : public AbstractShape
{
private:
    std::string colour;
    std::string surface;

public:
    ColourAndSurfaceRectangle(float h, float w, std::string colour = "", std::string shape = "");
    std::string get_description();
};


// main/shape.cc

#include "shape.h"
#include <vector>
#include <string>
#include <iostream>

float calculate_area(std::vector<AbstractShape> shape_arr)
{
    float sum = 0;
    for (AbstractShape shape : shape_arr)
    {
        sum += shape.get_area();
    }
    return sum;
}

float AbstractShape::get_area()
{
    return area;
}

void AbstractShape::describe()
{
    std::string description = this->get_description();
    std::cout << description << std::endl;
}

Rectangle::Rectangle(float h, float w)
{
    this->shape_name = "Rectangle";
    this->area = h * w;
    this->perimeter = 2 * (h + w);
}

std::string Rectangle::get_description()
{
    std::string description = "Shape:" + this->shape_name + "\n" +
                              "Perimeter: " + std::to_string(this->perimeter) + "\n" +
                              "Area: " + std::to_string(this->area) + "\n";

    return description;
}

ColourAndSurfaceRectangle::ColourAndSurfaceRectangle(float h, float w, std::string colour, std::string shape)
{
    this->shape_name = "Rectangle";
    this->area = h * w;
    this->perimeter = 2 * (h + w);
    this->colour = colour;
    this->surface = surface;
}

std::string ColourAndSurfaceRectangle::get_description()
{
    std::string description = "Shape:" + this->shape_name + "\n" +
                              "Perimeter: " + std::to_string(this->perimeter) + "\n" +
                              "Area: " + std::to_string(this->area) + "\n";
    if (this->colour != "")
    {
        description += "Colour: " + this->colour + "\n";
    }
    if (this->surface != "")
    {
        description += "Surface: " + this->surface + "\n";
    }

    return description;
}

AbstractShape factory_method(float h, float w, std::string colour, std::string surface)
{
    if (colour != "" || surface != "")
    {
        return ColourAndSurfaceRectangle(h, w, colour, surface);
    }
    return Rectangle(h, w);
}

最后是測試文件夾

# test/BUILD

cc_test(
    name = "shape_test",
    size = "small",
    srcs = ["shape_test.cc"],
    deps = [
        "//main:shape",
        "@com_google_googletest//:gtest_main",
    ],
)

// test/shape_test.cc

#include <gtest/gtest.h>
#include "main/shape.h"
#include <string>

TEST(ColourAndSurfaceRectangleTest, ShapeTest)
{


    std::string expected_str = "Shape: Rectangle\n"
                               "Perimeter: 10\n"
                               "Area: 6\n"
                               "Colour: Blue\n"
                               "Surface: Stained\n";
    AbstractShape shape = factory_method(3, 2, "Blue", "Stained");
    EXPECT_EQ(shape.get_description(), expected_str);
}

我現在運行以下命令 - bazel test --test_output=all //test:shape_test ,但我得到了這個無法辨認的錯誤 -

INFO: From Testing //test:shape_test:
==================== Test output for //test:shape_test:
dyld[37648]: symbol not found in flat namespace (__ZTV13AbstractShape)
================================================================================

“找不到符號”是什么意思? 以前有人在 macOS 上遇到過與 Bazel/cpp 類似的問題嗎?

該錯誤意味着並非所有虛擬方法都已定義。 確切的一個虛擬AbstractShape::get_description未定義。 我猜從類名來看,成員函數一定是純虛的

virtual std::string get_description() = 0;
//                                    ^

該類必須具有虛擬析構函數

virtual ~AbstractShape() = default;

謝謝。 原來我缺少一個虛擬析構函數,而且我沒有將成員函數設為純虛擬。

這是有效的最終 cpp 文件 -

#include "shape.h"
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
#include "fmt/core.h"

float calculate_area(std::vector<AbstractShape *> shape_arr)
{
    float sum = 0;
    for (AbstractShape *shape : shape_arr)
    {
        sum += shape->get_area();
    }
    return sum;
}

float AbstractShape::get_area()
{
    return area;
}

void AbstractShape::describe()
{
    std::string description = this->get_description();
    std::cout << description << std::endl;
}

Rectangle::Rectangle(float h, float w)
{
    this->shape_name = "Rectangle";
    this->area = h * w;
    this->perimeter = 2 * (h + w);
}

std::string Rectangle::get_description()
{
    std::string description = "Shape:" + this->shape_name + "\n" +
                              "Perimeter: " + fmt::format("{:.2f}", this->perimeter) + "\n" +
                              "Area: " + fmt::format("{:.2f}", this->area) + "\n";

    return description;
}

ColourAndSurfaceRectangle::ColourAndSurfaceRectangle(float h, float w, std::string colour, std::string surface)
{
    this->shape_name = "Rectangle";
    this->area = h * w;
    this->perimeter = 2 * (h + w);
    this->colour = colour;
    this->surface = surface;
}

std::string ColourAndSurfaceRectangle::get_description()
{
    std::string description = "Shape:" + this->shape_name + "\n" +
                              //   "Perimeter:" + std::to_string(this->perimeter) + "\n" +
                              "Perimeter:" + fmt::format("{:.2f}", this->perimeter) + "\n" +
                              "Area:" + fmt::format("{:.2f}", this->area) + "\n";
    if (this->colour != "")
    {
        description += "Colour:" + this->colour + "\n";
    }
    if (this->surface != "")
    {
        description += "Surface:" + this->surface + "\n";
    }

    return description;
}

AbstractShape *factory_method(float h, float w, std::string colour, std::string surface)
{
    if (colour != "" || surface != "")
    {
        return new ColourAndSurfaceRectangle(h, w, colour, surface);
    }
    return new Rectangle(h, w);
}

和頭文件 -

#ifndef MAIN_SHAPE_H_
#define MAIN_SHAPE_H_

#include <string>
#include <vector>

class AbstractShape
{
protected:
    float area;
    float perimeter;
    std::string shape_name;

public:
    float get_area();
    void describe();
    virtual std::string get_description() = 0;
    virtual ~AbstractShape() = default;
};

AbstractShape *factory_method(float h, float w, std::string colour = "", std::string surface = "");

float calculate_area(std::vector<AbstractShape*> shape_arr);

class Rectangle : public AbstractShape
{

public:
    Rectangle(float h, float w);
    std::string get_description();
};

class ColourAndSurfaceRectangle : public AbstractShape
{
private:
    std::string colour;
    std::string surface;

public:
    ColourAndSurfaceRectangle(float h, float w, std::string colour = "", std::string shape = "");
    std::string get_description();
};

#endif

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM